4

以下のコードでは、ブロックが呼び出されたときに画像オブジェクトが存続することを保証するために、selfが保持されています。それはドキュメントが言うことです。しかし、その理由がわからないようです。画像を保持するだけで、割り当てが解除されないことが保証されます。では、なぜ自分自身も保持するのでしょうか。

self.finishBlock = ^{
    self.image.hidden = YES;
}

画像に直接アクセスする場合、これは当てはまりますか?

self.finishBlock = ^{
    _image.hidden = YES;
}
4

2 に答える 2

7

自己が保持されるのは

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つのアプローチは、自己の弱いバージョンをキャプチャし、それをブロックで使用することです。この場合、ブロックには、強いではなく弱い自己への参照があります(つまり、自己を保持しません)。ただし、-imageselfのアクセサメソッドは引き続き呼び出されるため、ブロックが実行される前にイメージが変更された場合は、新しい値が使用されます。

__weak YourClass *weakSelf = self;
self.finishBlock = ^{
    weakSelf.image.hidden = YES;
}

この場合、selfブロックが実行される前に割り当てが解除weakSelfされると、nilになり、ブロック内のステートメントは事実上NOOPになることに注意してください(nilに送信されるメッセージはObjective-Cでは何もしません)。

于 2013-01-28T16:50:32.520 に答える
3

ブロックは、キャプチャされたオブジェクトをブロック内に保持する必要があります。最初のブロックの例は実際には次のとおりです。

self.finishBlock = ^{
    [[self image] setHidden:YES];
}

ブロックはself、メソッドを適切に呼び出すことができるように保持する必要がありますimage。書かれているように、ブロックが実行されてメソッドが呼び出されるimageまで画像が取得されないため、ブロックを単純に保持することはできません。imageしたがって、ここでの唯一のオプションは、を保持することselfです。

2番目のブロックには、実際に次のものがあります。

self.finishBlock = ^{
    self->_image.hidden = YES;
}

したがって、ブロックが実際に実行されるときにivarselfの適切な値にアクセスできるように、保持する必要があります。_image

于 2013-01-28T16:54:44.423 に答える