10

ブロックを使用する場合、一部の変数には __block が必要で、関数パラメーターなどの他の変数には必要ないのはなぜですか?

4

2 に答える 2

30

質問は本当に間違った言い回しです。「いつ__blockが必要なのか?」ではなく、「__blockは何をするのか?」です。それが何をするのかを理解すれば、いつそれが必要なのかがわかります。

通常、ブロックが変数をキャプチャすると (ブロックがそれ自体の外部の変数を参照するときにキャプチャが発生します)、変数のコピーが作成されます (オブジェクトの場合、オブジェクト自体ではなくポインターのコピーが作成されることに注意してください)。オブジェクトの場合は保持します。

つまり、通常の動作では、ブロックを使用してブロック外の値を変更することはできません。このコードは無効です。たとえば、次のようになります。

int x = 5;
void(^block)() = ^{ x = 10; };

__block 修飾子は 2 つの変更を行います。最も重要なのは、ブロックがコピーを作成するのではなく、ブロックを直接キャプチャする必要があることをコンパイラに伝えることです。つまり、ブロック外の変数の値を更新できます。それほど重要ではありませんが、ARC を使用していない場合は、キャプチャされたオブジェクトを保持しないようにコンパイラに指示します。

于 2013-02-07T19:13:45.490 に答える
15

コード ブロックは、ブロックが宣言されたスコープ内にあるすべての変数にアクセスできます。ただし、ブロックのスコープ外で宣言された変数/オブジェクトは、ブロック内で不変です。読むことはできますが、変更することはできません。オブジェクトの宣言で __block フラグを設定すると、ブロックのスコープ内で変更できます。

編集:ここに例があります:

NSString *myString = @"hello";
dispatch_sync(dispatch_get_main_queue(), ^{
    myString = @"hello world";
});

これは機能せず、エラー メッセージが表示されます。

__block NSString *myString = @"hello";
dispatch_sync(dispatch_get_main_queue(), ^{
    myString = @"hello world";
});

問題が解決しました!

于 2013-02-07T19:13:18.963 に答える