1

例えば:

[self.contentWrapperView addGestureRecognizer:
   [UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender, 
                                                   UIGestureRecognizerState state, 
                                                   CGPoint location) {
        if (self.customEditing) {
        [self setEditingMode:NO Animated:YES];
      }
    }]];

wherecontentWrapperViewは の強力なプロパティでselfあり、推定contentWrapperViewには認識ブロックへの強力な参照があります。ブロックで使用selfすると、保持サイクルが発生しますか? この部分だけがよくわかりません。

4

2 に答える 2

4

リテイン サイクルについて、それが実際に何であるかという観点から考えてみましょう。つまり、自分が所有するオブジェクトによる自分自身のリテンションです。

Cocoa と Cocoa-Touch の用語で言えば、あなたが強く所有している変数は、あなたを強く所有することはできないということです。これは、多くの場合、親を所有する必要があるプロパティを宣言することで回避できます。これはブロックによって複雑になり、クロージャーが通常行うように、ブロック内のすべての変数への const または保持された参照をキャプチャします (明らかに、修飾子によってさらに複雑になります)。weakunsafe_unretainedassign__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.
}]];
于 2013-03-26T21:06:44.053 に答える
4

はい、保持サイクルにつながります。

気になる場合の回避策は

__weak id weakSelf = self;
[self.contentWrapperView addGestureRecognizer:[UITapGestureRecognizer recognizerWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) {
    if ([weakSelf customEditing]) {
        [weakSelf setEditingMode:NO Animated:YES];
    }
}]];
于 2013-03-26T20:51:11.080 に答える