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


367

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

copyは明らかにまったく別のものですがstrongvs retainweakvsの間に違いはありますassignか?

私の理解では、ここでの唯一の違いは、ポインターにweak割り当てnilられることですが、割り当てられassignません。つまり、解放されたポインターにメッセージを送信すると、プログラムがクラッシュします。しかし、私がを使用する場合weak、これは起こりません。なぜなら、メッセージ送信nilは何もしないからです。

私は間の違いを知らないstrongretain

私が使用すべき理由何らかの理由があるassignretain新しいプロジェクトで、または廃止さのようなものですか?


12
そこARCにより導入された性質のための3つの新しいメモリ管理属性はstrongweakunsafe_unretained
NJones 2012年

5
@NJonesがあります。2つのプロパティ属性(weakstrong)と4回の変数の寿命予選(__strong__weak__unsafe_unretained__autoreleasing)。以下のARCノートを参照してください。
Snowcrash、2013

1
@SnowCrash assignARCでコンパイルするときに使用するとエラーになるバージョンのXcode、おそらく開発者プレビューがありました。これについては削除された答えがたくさんあります。最終リリース前に変更されたようです。unsafe_unretained私たちの多くのアーリーアダプターにとって好ましい属性です。これunsafe_unretainedが有効な属性であることの証明については、「一部のクラスには安全でない保持されていない参照を使用する」の「データのカプセル化」セクションにあるAppleの「Programming With Objective-C」を参照してください。「プロパティの場合、これはunsafe_unretained属性を使用することを意味します。」
NJones

回答:


230

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

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

@property(strong) MyClass *myObject;

だから、strong同じであるretainプロパティ宣言では。

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


11
実際、ARCではassign、オブジェクトに使用するのはコンパイルエラーです。プロパティを保持したくない場合は、weakまたはunsafe_unretained(明らかに安全ではありません)を使用する必要があります。
cobbal 2012年

5
assignデプロイメントターゲット4.0を使用したARCプロジェクトで、私にとっては問題なくコンパイルできます。
Pascal、

8
@Pascal:osが5.0以上でないデプロイメントターゲットでは、弱参照は許可されません。したがって、古いプロジェクトでは割り当てを使用できますが、新しいバージョンに移行する場合は、weakに切り替える必要があります
Mattia

1
Xcode 4(ARC付き)はvs を使用してNSManagedObjectサブクラスを生成するように見えます。それはほとんど無害だと思いますが、一貫性を保つためにあるべきだと思います...あるいはおそらく問題ではありません。stackoverflow.com/questions/7796476/...retainstrongstrong
ジョーD'アンドレア

3
@JeremyPはい、あなたの答えは正解です。@Mattiaに反応していました。assign一部のケースではまだ有効であることを指摘していました。
Steven Oxley

606

Stackoverflowの投稿と変数アプリケーションの属性を確認するデモアプリケーションをたくさん読んだ後、すべての属性情報をまとめることにしました。

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

以下は、上記のすべての属性を見つけることができる詳細な記事のリンクであり、間違いなく役立ちます。ここで最高の答えをくれたすべての人々に感謝します!!

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

1.strong(iOS4 =保持)

  • 「もう指さなくなるまで、これをヒープ内に保持してください」と書かれています
  • 言い換えれば、「私は所有者です。保持するのと同じことで、狙いを定める前に割り当てを解除することはできません」
  • オブジェクトを保持する必要がある場合にのみ、strongを使用します。
  • デフォルトでは、すべてのインスタンス変数とローカル変数は強力なポインターです。
  • 通常、UIViewControllers(UIアイテムの親)にはstrongを使用します
  • strongはARCで使用され、オブジェクトの保持カウントについて心配する必要がないため、基本的にはを助けます。ARCは、使い終わったときに自動的に解放します。strongキーワードを使用すると、オブジェクトを所有していることになります。

例:

@property (strong, nonatomic) ViewController *viewController;

@synthesize viewController;

2.弱い -

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

例:

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

@synthesize myButton;

BJホーマーのおかげで、強くて弱い説明:

オブジェクトが犬であり、犬が逃げる(割り当て解除される)ことを望んでいると想像してください。

強力なポインタは、犬の鎖のようなものです。あなたが犬に紐を付けている限り、犬は逃げません。5人が1つの犬にリーシュを取り付けた場合(1つのオブジェクトへの5つの強いポインタ)、犬は5つすべてのリーシュが外れるまで逃げません。

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

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

弱く使うと?

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

3.retain = strong

  • それは保持され、古い値が解放されて割り当てられ、retainは新しい値を送信する必要があることを指定します
  • 割り当てを保持し、送信された古い値-リリース
  • 保持は強いと同じです。
  • Appleは、retainと書いた場合、自動変換/ strongのみのように動作すると述べています。
  • 「alloc」などのメソッドには、暗黙的な「retain」が含まれます

例:

@property (nonatomic, retain) NSString *name;

@synthesize name;

4.割り当て

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

例:

@property (nonatomic, assign) NSString *address;

@synthesize address;

5
2.「弱参照は、参照オブジェクトをガベージコレクターによるコレクションから保護しない参照」-ガベージコレクターなどの目的cにはありません。
ブッチャーランド2015年

1
この階層はiOSによって自動的に管理されます。MVCの概念についてお読みください。つまり、ViewContorllerが表示されているとき、iOSはそのビューの階層を画面に読み込みます(欠落しているビューを作成します)。他のViewControllerが表示されると、このビューの最初の階層が割り当て解除されます。しかし、ViewControllerに「strong」がある場合、画面がオフのとき、このビューの割り当てを解除することはできません。これはデバイスのメモリに大きな影響を与え、アプリの速度低下の原因となる可能性があります。(もちろん、デバイスには大量のメモリがあり、5〜10画面のアプリでは問題ありませんが、巨大なアプリでは問題が発生します)
bucherland

1
弱く使うと?1. UIオブジェクトの場合、2。デリゲート、3。ブロック(メモリサイクルを回避するには、セルフの代わりにweakSelfを使用する必要があります(前述のとおり))
bucherland

1
このすばらしい答えには間違いが1つあります-強力-「ARCは、使い終わったときに自動的に解放します」。これは正しくありません。ARCは、弱いオブジェクトへのポインタがない場合に自動的に解放します。強い-保持することの同義語であり、オブジェクトが保持されるため、オブジェクトをnilにするのは私たちの責任です
Ashwin G

1
@RDC、どういうdefault意味ですか?私が使用している場合は@property (nonatomic) NSString *stringそれがありますかstrong?それともassign?どちらもデフォルトだからです。
ユリアンオノフレイ16

40

非原子/原子

  • 非原子は原子よりもはるかに高速です
  • アトミックの非常に具体的な要件がない限り、常に非アトミックを使用します(これはまれです)(アトミックはスレッドの安全性を保証しません-別のスレッドによって同時に設定されている場合にのみ、プロパティへのアクセスを停止します)。

強い/弱い/割り当て

  • 使用する オブジェクトを保持する strongを -キーワードのretainは同義語ですが、代わりにstrongを使用するのが最善です
  • オブジェクトを保持せずにオブジェクトへのポインターのみが必要な場合は、weakを使用します。保持サイクル(デリゲートなど)を回避するのに役立ちます。オブジェクトが解放されると、ポインターは自動的にnilになります。
  • プリミティブに割り当てを使用-解放時にオブジェクトをnilで除外しないことを除いて、weakとまったく同じ(デフォルトで設定)

(オプション)

写す

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

読み取り専用

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

@Sakthimuthiahは正しい、あなたはあなたの答えを修正する必要があります。
Adela Toderici 16

@Sakthimuthiahは正しくありません(そしてそれを言う人は誰でも)。アトミックはスレッドセーフにしませんが、その動作のために簡単に誤解される可能性があります。お読みください:stackoverflow.com/questions/12347236/...
クリス・J

39

私の知る限り、strongそしてretain同義語なので、正確に同じ。

その後、weakほとんどのようですassignいますが、オブジェクトが指しているオブジェクトが割り当て解除されると、自動的にnilに設定されます。

つまり、単にそれらを置き換えることができます。

しかし、そこに私が使用していた私が遭遇した1特殊なケースは、あるassign、というよりもweak。2つのプロパティdelegateAssignとがあるとしdelegateWeakます。どちらにも、デリゲートが格納されています。これは、唯一の強い参照を持つことで私たちを所有しています。デリゲートは割り当てを解除しているので、-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変数がどのように機能し、いつ無効化されるかがわかります。



20

Objective-C自動参照カウント(ARC)に関するClangのドキュメントには、所有権の修飾子と修飾子が明確に説明されています。

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

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

型が__ autoreleasing、__ strong、または__ weakで修飾されている場合、型は自明な所有権修飾です。

次に、宣言されたプロパティには6つの所有権修飾子があります。

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

weakを除いて、これらの修飾子は非ARCモードで使用できます。

意味論的には、所有権修飾子は5つの管理対象操作(読み取り、割り当て、初期化、破棄、移動)で異なる意味を持ち、ほとんどの場合、割り当て操作の違いのみを考慮します。

割り当ては、割り当て演算子を評価するときに発生します。セマンティクスは資格によって異なります。

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

読み取り、初期化、破壊、移動のその他の違いについては、ドキュメントのセクション4.2「セマンティクス」を参照してください。


6

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

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

上記のメソッドでは、myName変数のスコープはdisplayLocalVariableメソッドに制限されています。メソッドが完了すると、文字列「ABC」を保持しているmyName変数がメモリから割り当て解除されます。

次に、ビューコントローラのライフサイクル全体でmyName変数の値を保持したい場合はどうでしょう。このために、self.username = myName;以下のように、変数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」文字列への強い参照を持っています)。したがって、self.usernameが有効になるまで、文字列myNameはメモリから割り当て解除されません。

  • 弱い参照

ここで、myNameをダミー参照であるself.dummyName = myNameに割り当てることを検討してください。ストロングリファレンスとは異なり、ウィークは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に到達します。

お役に立てれば。


2

強い:

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

例:@property(強力、非アトミック)ViewController * viewController;

@synthesize viewController;

弱い

デフォルトで自動的に取得してnilに設定

  • 通常、IBOutlets(UIViewControllerの子)とデリゲートにはウィークを使用します
  • 割り当てと同じこと、保持または解放なし

例:@property(弱い、非アトミック)IBOutlet UIButton * myButton;

@synthesize myButton;


1

強いと保持の違い:

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

弱いと割り当ての違い:

  • 「弱い」参照とは、保持していない参照であり、他の誰かが強く参照している限り保持します。
  • オブジェクトが「割り当て解除」されると、ウィークポインターは自動的にnilに設定されます
  • 「割り当て」プロパティ属性は、プロパティのセッター実装を合成する方法をコンパイラーに指示します
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.