リテイン サイクルについて、それが実際に何であるかという観点から考えてみましょう。つまり、自分が所有するオブジェクトによる自分自身のリテンションです。
Cocoa と Cocoa-Touch の用語で言えば、あなたが強く所有している変数は、あなたを強く所有することはできないということです。これは、多くの場合、親を所有する必要があるプロパティを宣言することで回避できます。これはブロックによって複雑になり、クロージャーが通常行うように、ブロック内のすべての変数への const または保持された参照をキャプチャします (明らかに、修飾子によってさらに複雑になります)。weak
unsafe_unretained
assign
__block
これをブロックの観点から見るのではなく、2 つのクラスを持つ例に抽象化してみます。
MyImportantObject
別の class で何らかの作業を行う必要があるclassがあるとしますMyWorkerClass
。通常は への強力な参照がMyWorkerClass
必要です。これは、あとでもう少し作業を行うことができるようにするため、または同じワーカー メソッドを何度も呼び出し続けることができるようにするためです。
@interface MyImportantObject : NSObject
@property (nonatomic, strong) MyWorkerClass *workerObj;
@end
次に、ワーカーは、動作するために必要なすべてのMyImportantObject
のプロパティへの安定した参照を必要とします (そうでなければ動作しません! )。したがって、その参照ブロックself
は、すべての変数への const または保持された参照を取得する代わりに、親への保持された参照を取得します!
@interface MyWorkerClass : NSObject
@property (nonatomic, strong) MyImportantObject *workerObj;
@end
これが意味することは、MyImportantObject
のワーカー オブジェクトを使用しようとすると、それらは互いに保持され、どちらも適切に割り当て解除されないということです! 巨大なノーノー。
(またはMRC の下で) ポインターにシャントself
することで、代わりに次のような参照を取得します。__weak
__block
@interface MyWorkerClass : NSObject
@property (nonatomic, weak) MyImportantObject *workerObj;
@end
親が恐竜の道を行くと、誰もが適切に割り当てを解除されます。
しかし、もう 1 つパズルのピースがあります。それは、weak
参照をどうするかということです。結局のところ、古き良きコンパイラがやって来て、self
あなたの下から素早く引っ張ってきたとしましょう-release
。弱いポインターをゼロにするため、ブロック内で nil ポインターが暴走しています。これは、そこに座って頭をかきむしっている間、文字通り何もしないことにつながる可能性があります。これが、弱い強いダンスと私が呼ぶものを発明することにつながりました.
J_mcnally の例には、ダンスの重要なステップが 1 つ欠けています。自己ポインターの「再強化」です。しかし、保持サイクルを回避するためにあらゆる苦労をしたのに、なぜそれをしたいのでしょうか? これは、X の強力なコピーがブロックによって保持されず、ブロックのスコープによって保持されるためです。英語では、これはself
、ブロックの終わりに達した場合にのみストロングが解放されることを意味し、安全なメモリサイクルを保証するだけでなく、私たちの下から解放されないことを保証します. 適切な修正は次のようになります。
__weak id weakSelf = self;
[self.contentWrapperView addGestureRecognizer:[UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) {
id strongSelf = weakSelf;
if ([strongSelf customEditing]) {
[strongSelf setEditingMode:NO Animated:YES];
}
//Do some other stuff before strongSelf passes out of scope.
}]];