自己が保持されるのは
self.image.hidden = YES;
実は
[[self image] setHidden:YES];
[self image]
ブロックが実行され、画像を取得するために呼び出されるまで利用できないため、画像を直接保持することはできません。
2番目の例も、少し異なる理由で、自己を保持しています。Objective-Cでは、インスタンス変数に直接アクセスすると、実際には、selfの基礎となる構造体を介してアクセスされます。つまり、_image
実際にはself->_image
コンパイル後です。この場合も、ブロックは自己にアクセスする必要があるため、自己を保持します。
また、どちらの場合でも、ブロックが実行される前に_imageの値が変更されると、ブロックは新しい値を「認識」することにも注意してください。それはしばしばですが、常にあなたが望むものではありません。
自己保持を避けるための2つのオプションがあります。1つ目はこれを行い、ブロックが定義された時点で_imageの値をキャプチャするため、変更された場合でも、ブロックには元の値が表示されます。このアプローチは、ローカル変数を定義し、それをによって返される現在の値に設定してからself.image
、ブロックでそれを使用することです。
UIImage *image = self.image;
self.finishBlock = ^{
image.hidden = YES;
}
もう1つのアプローチは、自己の弱いバージョンをキャプチャし、それをブロックで使用することです。この場合、ブロックには、強いではなく弱い自己への参照があります(つまり、自己を保持しません)。ただし、-image
selfのアクセサメソッドは引き続き呼び出されるため、ブロックが実行される前にイメージが変更された場合は、新しい値が使用されます。
__weak YourClass *weakSelf = self;
self.finishBlock = ^{
weakSelf.image.hidden = YES;
}
この場合、self
ブロックが実行される前に割り当てが解除weakSelf
されると、nilになり、ブロック内のステートメントは事実上NOOPになることに注意してください(nilに送信されるメッセージはObjective-Cでは何もしません)。