web-dev-qa-db-ja.com

Objective-C ARC:強いと保持、弱いと割り当て

ARCによって導入されたプロパティのための2つの新しいメモリ管理属性、strongweakがあります。

明らかにまったく異なるcopyとは別にstrong vs retainweak vs assignの間に違いはありますか?

私の理解したところでは、ここでの唯一の違いはweakがポインタにnilを代入するのに対して、assignはポインタに代入しないということです。しかし、私がweakを使ったとしても、これは起こりません。なぜなら、nilへのメッセージ送信は何もしないからです。

strongretainの違いについては知りません。

新しいプロジェクトでassignretainを使うべきなのか、それとも廃止予定なのか、という理由がありますか?

358
Jakub Arnold

ARCリリースノートへの移行 (プロパティ属性のセクションの例)から。

// The following declaration is a synonym for: @property(retain) MyClass *myObject;

@property(strong) MyClass *myObject;

したがって、strongはプロパティ宣言のretainと同じです。

ARCプロジェクトでは、strongの代わりにretainを使用します。Cプリミティブプロパティにはassignを使用し、Objective-Cオブジェクトへの弱い参照にはweakを使用します。

228
JeremyP

Stackoverflowの投稿とデモアプリケーションを使って可変プロパティの属性をチェックするためのたくさんの記事を読んだ後、すべての属性情報をまとめることにしました。

  1. アトミック//デフォルト
  2. 非原子
  3. strong =保持//デフォルト
  4. 弱い
  5. 保持する
  6. //デフォルトを割り当てる
  7. unsafe_unretained
  8. コピーする
  9. 読み取り専用
  10. readwrite //デフォルト

以下は、上記のすべての属性を見つけることができる詳細な記事へのリンクです。ここで最高の答えを与えるすべての人々に感謝します!

iOSの可変プロパティ属性または修飾子

1.strong(iOS4 =保持)

  • それが「私がもうそれを指摘しなくなるまでこれをヒープの中に保ってください」と言います
  • 言い換えれば、「私は所有者です、あなたは保持するのと同じことでうまく狙う前にこれを解放することはできません」
  • オブジェクトを保持する必要がある場合にのみ強いを使用します。
  • デフォルトでは、すべてのインスタンス変数とローカル変数は強いポインタです。
  • UIViewControllers(UIアイテムの親)には通常strongを使用します。
  • aRCと一緒に使用され、それは基本的にあなたがオブジェクトの保持数を心配する必要はありませんので、役立ちます。 ARCは、それが完了したら自動的に解放します。キーワードstrongを使用すると、そのオブジェクトを所有していることになります。

例:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

2.弱 -

  • それは「他の誰かが強くそれを指している限りこれを守る」と言っています
  • 代入、保持、解放と同じこと
  • 「弱い」参照は、あなたが保持していない参照です。
  • 通常、IBOutlets(UIViewControllerのChilds)にはweakを使用します。これは、親オブジェクトが存在する限り子オブジェクトが存在する必要があるためです。
  • 弱い参照は、参照オブジェクトをガベージコレクタによるコレクションから保護しない参照です。
  • 弱いとは、本質的に、保持されていないプロパティを割り当てることです。オブジェクトの割り当てが解除されたときを除いて、弱いポインタは自動的にnilに設定されます。

例:

@property (weak, nonatomic) IBOutlet UIButton *myButton;

@synthesize myButton;

強くて弱い説明、 BJ Homerのおかげで

私たちの物が犬であり、その犬が逃げたい(解放される)ことを想像してください。

強い指針は犬のひものようなものです。あなたが犬にひもを付けている限り、犬は逃げません。 5人が1匹の犬にひもをつけると(1つのオブジェクトに5つの強いポインタ)、その犬は5つすべてのひもが外れるまで逃げません。

一方、弱いポ​​インタは、小さな子供が犬を指差して「見て!犬!」と言っているようなものです。犬がまだひもにつながっている限り、小さな子供たちはまだ犬を見ることができ、彼らはまだそれを指し示すでしょう。しかし、すべての綱が外れるとすぐに、何人の子供がそれを指していても犬は逃げます。

最後の強いポインタ(リーシュ)がオブジェクトを指していなくなるとすぐに、そのオブジェクトは割り当て解除され、すべての弱いポインタはゼロにされます。

弱いと使うと?

あなたがweakを使いたい唯一の時は、保持サイクルを避けたい場合です(例えば、親は子を保持し、子は親を保持するのでどちらも解放されません)。

3.保持=強い

  • 保持され、古い値が解放され、割り当てられます。新しい値を送信するように指定します。
  • 代入時に保持し、古い値を送信
  • 保持は強いと同じです。
  • Appleは、あなたが「保持する」と書いた場合、それは自動変換され/強いだけのように働くだろうと言います。
  • "alloc"のようなメソッドは暗黙の "retain"を含みます

例:

@property (nonatomic, retain) NSString *name;

@synthesize name;

4.割り当て

  • assignがデフォルトで、単純に変数代入を実行します
  • assignは、プロパティのセッター実装を合成する方法をコンパイラに指示するプロパティ属性です。
  • Cのプリミティブプロパティにはassignを、Objective-Cオブジェクトへの弱い参照にはweakを使います。

例:

@property (nonatomic, assign) NSString *address;

@synthesize address;
594
swiftBoy

私の知る限りでは、strongretainは同義語なので、もまったく同じです。

その場合、weakはほぼassignに似ていますが、オブジェクトが指しているオブジェクトの割り当てが解除されると、自動的にnilに設定されます。

つまり、単純に置き換えることができます

しかし、assignではなくweakを使用しなければならないという特別なケースが1つあります。 delegateAssigndelegateWeakという2つのプロパティがあるとしましょう。どちらにも、私たちのデリゲートが格納されています。それは、唯一の強い参照を持つことによって私たちを所有しているということです。デリゲートは解放されているので、私たちの-deallocメソッドも呼ばれます。

// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
    [delegateWeak doSomething];
    [delegateAssign doSomething];
}

デリゲートはすでに割り当て解除プロセスに入っていますが、まだ完全に割り当て解除されていません。問題は、weakへの参照はすでに無効化されていることですプロパティdelegateWeakにはnilが含まれますが、delegateAssignには有効なオブジェクトが含まれますまだ有効)。

// Our delegate is deallocating and there is no other strong ref.
- (void)dealloc {
    [delegateWeak doSomething]; // Does nothing, already nil.
    [delegateAssign doSomething]; // Successful call.
}

これは非常に特殊なケースですが、これらのweak変数がどのように機能するのか、またいつ無効にされるのかがわかります。

39
Tricertops

非原子/原子

  • 非原子は原子よりはるかに速い
  • アトミックに特別な要件がある場合を除き、常に非アトミックを使用します。アトミックはスレッドの安全性を保証するものではありません。同時に別のスレッドによって設定されている場合にのみアクセスします。

強/弱/代入

  • オブジェクトを保持するにはstrongを使用します - キーワードretainは同義ですが、代わりにstrongを使用するのが最善です。
  • 保持しないでオブジェクトへのポインタだけを取得したい場合はweakを使用します。保持サイクル(デリゲート)を回避するのに役立ちます - オブジェクトが解放されると自動的にポインタを消去します。
  • プリミティブにassignを使用 - 解放されたときにオブジェクトをゼロにしないことを除けば厳密にweakと同じです(デフォルトで設定されています)。

(オプション)

コピー

  • オブジェクトの浅いコピーを作成するためにそれを使用してください
  • 不変プロパティを常にコピーに設定することをお勧めします - 不変バージョンは不変プロパティに渡すことができるので、copyは常に不変オブジェクトを扱うことを保証します。
  • 不変オブジェクトが渡されてもそれは保持されます - 可変オブジェクトが渡されるとそれはそれをコピーします

読み取り専用

  • プロパティの設定を無効にするために使用します(違反がある場合はコードがコンパイルされないようにします)。
  • インスタンス変数を介して直接変数を変更するか、getterメソッド自体の中でゲッターによって提供されるものを変更することができます。
38
Vadoff

Objective-C自動参照カウント(ARC)に関するClangの文書 は、所有権の修飾子と修飾子を明確に説明しています。

4つの所有権修飾子があります。

  • __自動解放
  • __強い
  • __ * unsafe_unretained *
  • __弱い

型が__自動解放、__強い、または__弱いで修飾されている場合、その型は重要な所有権で修飾されます。 ).

それから宣言された財産のための6つの所有権修飾子があります:

  • assignは__ * unsafe_unretained *所有権を意味します。
  • copyは、__強い所有権、およびセッターでのコピーセマンティクスの通常の動作を意味します。
  • retainは__強い所有権を意味します。
  • 強いは__強い所有権を意味します。
  • * unsafe_unretained *は__ * unsafe_unretained *の所有権を意味します。
  • 弱いは__弱い所有権を意味します。

弱いを除いて、これらの修飾子は非ARCモードで利用可能です。

意味的には、所有権修飾子は、5つの管理対象操作で異なる意味を持ちます。つまり、読み取り、割り当て、初期化、破棄、および移動です。操作。

代入演算子を評価するときに代入が発生します。意味論は資格によって異なります。

  • __強いオブジェクトの場合、新しい指示先が最初に保持されます。次に、左辺値に原始的な意味がロードされます。第三に、新しい指示先は原始的な意味で左辺値に格納されます。そして最後に、古い指示者が解放されます。これはアトミックには実行されません。同時のロードおよびストアに直面しても、これを安全にするために外部同期を使用する必要があります。
  • __弱いオブジェクトの場合、新しい指示先が現在割り振り解除中のオブジェクトでない限り、左辺値は新しい指示先を指すように更新されます。この場合、左辺値はNULLポインターに更新されます。これは、オブジェクトへの他の割り当て、オブジェクトからの読み込み、および新しい指示先の最終リリースへのアトミックに実行する必要があります。
  • __ * unsafe_unretained *オブジェクトの場合、新しい指示先はプリミティブセマンティクスを使用して左辺値に格納されます。
  • __自動解放オブジェクトの場合、新しい指示先は保持され、自動解放され、プリミティブセマンティクスを使用して左辺値に格納されます。

Reading、Init、Destruction、およびMovingの他の違いは、この文書の セクション4.2のセマンティクス を参照してください。

20
Mingming

強弱参照を理解するために、以下の例を考慮して、displayLocalVariableという名前のメソッドがあるとします。

 -(void)displayLocalVariable
  {
     NSString myName = @"ABC";
     NSLog(@"My name is = %@", myName);
  }

上記のメソッドの範囲では、myName変数の範囲はdisplayLocalVariableメソッドに限定され、メソッドが終了すると、文字列 "ABC"を保持しているmyName変数はメモリから解放されます。

ビューコントローラのライフサイクル全体を通してmyName変数の値を保持したい場合はどうなりますか。このために、以下のように、変数myNameを強く参照するusernameという名前のプロパティを作成できます(以下のコードのself.username = myName;を参照)。

@interface LoginViewController ()

@property(nonatomic,strong) NSString* username;
@property(nonatomic,weak) NSString* dummyName;

- (void)displayLocalVariable;

@end

@implementation LoginViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

}

-(void)viewWillAppear:(BOOL)animated
{
     [self displayLocalVariable];
}

- (void)displayLocalVariable
{
   NSString myName = @"ABC";
   NSLog(@"My name is = %@", myName);
   self.username = myName;
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}


@end

上記のコードで、myNameがself.usernameに割り当てられ、self.usernameがmyNameへの強い参照(@propertyを使用して宣言したように)を持っていることがわかります(間接的に "ABC"文字列への強い参照を持ちます)。したがって、文字列myNameは、self.usernameが有効になるまでメモリから解放されません。

  • 弱い参照

今度は弱い参照であるdummyNameにmyNameを割り当てることを検討してください。self.dummyName = myName;厳密な参照とは異なり、Weakは、myNameへの強力な参照があるまでのみmyNameを保持します。弱い参照を理解するために以下のコードを見てください、

-(void)displayLocalVariable
  {
     NSString myName = @"ABC";
     NSLog(@"My name is = %@", myName);
     self.dummyName = myName;
  }

上記のコードでは、myNameへの弱い参照があります(つまり、self.dummyNameはmyNameへの弱い参照を持っています)が、myNameへの強い参照はないため、self.dummyNameはmyName値を保持できません。

今度はまた下記のコードを考慮しなさい、

-(void)displayLocalVariable
      {
         NSString myName = @"ABC";
         NSLog(@"My name is = %@", myName);
         self.username = myName;
         self.dummyName = myName;
      } 

上記のコードでは、self.usernameはmyNameへの強い参照を持っています。そのため、myNameには強い参照が関連付けられているため、self.dummyNameはメソッドの終了後もmyNameの値を持ちます。

変数への強い参照を行うたびに、保持カウントは1つ増えて変数は割り当て解除されず、保持カウントは0になります。

お役に立てれば。

4
Mahadev Mandale

強い:

  • プロパティは破棄されませんが、プロパティをnilに設定した場合に限り、オブジェクトは破棄されます。
  • デフォルトでは、すべてのインスタンス変数とローカル変数は強いポインタです。
  • オブジェクトを保持する必要がある場合にのみ強いを使用します。
  • UIViewControllers(UIアイテムの親)には通常strongを使用します。
  • IOS 4(ARC以外)保持することができるKeyWord
  • IOS 5(ARC)強力なキーワードを使用できる

例:@property(強力、非原子的)ViewController * viewController;

@synthesize viewController;

弱い

デフォルトでは自動的に取得してnilに設定されます

  • 私たちは一般的にIBOutlets(UIViewController's Childs)とデリゲートにweakを使います
  • 代入、保持、解放と同じこと

例:@property(弱い、非原子)IBOutlet UIButton * myButton;

@synthesize myButton;

2
Nikunj Patel

強いと保持の違いは次のとおりです。

  • IOS 4では、強いということは保持することに等しい
  • それはあなたがそのオブジェクトを所有し、もうそれを指し示さなくなるまでそれをヒープに保持することを意味します
  • あなたが保持を書く場合、それは自動的に強いのと同じように動作します

Weakとassignの違いは次のとおりです。

  • 「弱い」参照は、あなたが保持していない参照であり、他の誰かが強くそれを指している限りあなたはそれを保持します
  • オブジェクトの割り当てが解除されると、弱いポインターは自動的にnilに設定されます。
  • 「assign」プロパティ属性は、プロパティのセッター実装を合成する方法をコンパイラに指示します。
1
Chen Rui