ARCによって導入されたプロパティのための2つの新しいメモリ管理属性、strong
とweak
があります。
明らかにまったく異なるcopy
とは別に、strong
vs retain
とweak
vs assign
の間に違いはありますか?
私の理解したところでは、ここでの唯一の違いはweak
がポインタにnil
を代入するのに対して、assign
はポインタに代入しないということです。しかし、私がweak
を使ったとしても、これは起こりません。なぜなら、nil
へのメッセージ送信は何もしないからです。
strong
とretain
の違いについては知りません。
新しいプロジェクトでassign
とretain
を使うべきなのか、それとも廃止予定なのか、という理由がありますか?
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
を使用します。
Stackoverflowの投稿とデモアプリケーションを使って可変プロパティの属性をチェックするためのたくさんの記事を読んだ後、すべての属性情報をまとめることにしました。
以下は、上記のすべての属性を見つけることができる詳細な記事へのリンクです。ここで最高の答えを与えるすべての人々に感謝します!
1.strong(iOS4 =保持)
例:
@property (strong, nonatomic) ViewController *viewController;
@synthesize viewController;
2.弱 -
例:
@property (weak, nonatomic) IBOutlet UIButton *myButton;
@synthesize myButton;
強くて弱い説明、 BJ Homerのおかげで :
私たちの物が犬であり、その犬が逃げたい(解放される)ことを想像してください。
強い指針は犬のひものようなものです。あなたが犬にひもを付けている限り、犬は逃げません。 5人が1匹の犬にひもをつけると(1つのオブジェクトに5つの強いポインタ)、その犬は5つすべてのひもが外れるまで逃げません。
一方、弱いポインタは、小さな子供が犬を指差して「見て!犬!」と言っているようなものです。犬がまだひもにつながっている限り、小さな子供たちはまだ犬を見ることができ、彼らはまだそれを指し示すでしょう。しかし、すべての綱が外れるとすぐに、何人の子供がそれを指していても犬は逃げます。
最後の強いポインタ(リーシュ)がオブジェクトを指していなくなるとすぐに、そのオブジェクトは割り当て解除され、すべての弱いポインタはゼロにされます。
弱いと使うと?
あなたがweakを使いたい唯一の時は、保持サイクルを避けたい場合です(例えば、親は子を保持し、子は親を保持するのでどちらも解放されません)。
3.保持=強い
例:
@property (nonatomic, retain) NSString *name;
@synthesize name;
4.割り当て
例:
@property (nonatomic, assign) NSString *address;
@synthesize address;
私の知る限りでは、strong
とretain
は同義語なので、もまったく同じです。
その場合、weak
はほぼassign
に似ていますが、オブジェクトが指しているオブジェクトの割り当てが解除されると、自動的にnilに設定されます。
つまり、単純に置き換えることができます
しかし、、assign
ではなくweak
を使用しなければならないという特別なケースが1つあります。 delegateAssign
とdelegateWeak
という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
変数がどのように機能するのか、またいつ無効にされるのかがわかります。
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のセマンティクス を参照してください。
強弱参照を理解するために、以下の例を考慮して、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になります。
お役に立てれば。
例:@property(強力、非原子的)ViewController * viewController;
@synthesize viewController;
デフォルトでは自動的に取得してnilに設定されます
例:@property(弱い、非原子)IBOutlet UIButton * myButton;
@synthesize myButton;
強いと保持の違いは次のとおりです。
Weakとassignの違いは次のとおりです。