iVar
ブロック内のクラスのインスタンス変数へのアクセスは、コンパイラによって として解釈されself->iVar
ます。self
したがって、ブロックは変更されていないをキャプチャします。
__block
修飾子は にも機能すると確信しているdispatch_async
ため、これはドキュメントのエラーである可能性があります。
追加した
次の例は、__block
変数を で使用する方法を示していdispatch_async
ます。
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
__block int total = 0;
printf("address of total: %p\n", &total);
// dispatch some (concurrent) blocks asynchronously:
dispatch_async(queue, ^{
OSAtomicAdd32(5, &total);
});
dispatch_async(queue, ^{
OSAtomicAdd32(7, &total);
});
// Wait for all blocks to complete:
dispatch_barrier_sync(queue, ^{ });
printf("address of total: %p\n", &total);
printf("total=%d\n", total);
出力:
address of total: 0x7fff5fbff8f0
address of total: 0x100108198
total=12
total
ブロックが実行されると、スタックからヒープにコピーされることがわかります。
追加した
Blocks Programming Guideでこれを見つけました。__block
非同期ブロックで変数を使用しても問題がない理由を説明します。
__block 変数は、変数のレキシカル スコープと、変数のレキシカル スコープ内で宣言または作成されたすべてのブロックおよびブロック コピーとの間で共有されるストレージに存在します。したがって、フレーム内で宣言されたブロックのコピーがフレームの終わりを超えて存続する場合 (たとえば、後で実行するためにどこかでキューに入れられることによって)、ストレージはスタック フレームの破棄に耐えます。特定のレキシカル スコープ内の複数のブロックは、共有変数を同時に使用できます。
最適化として、ブロック ストレージはブロック自体と同じようにスタックから開始します。ブロックが Block_copy を使用して (またはブロックがコピーを送信された場合は Objective-C で) コピーされる場合、変数はヒープにコピーされます。したがって、__block 変数のアドレスは時間の経過とともに変化する可能性があります。