0

私はこれに似た方法を持っています:

- (void)loadStoreWithCompletion:(CompletionBlock)loadCompletion
{
    dispatch_queue_t loadQueue = dispatch_queue_create("loadQueue", DISPATCH_QUEUE_SERIAL);

    dispatch_async(loadQueue, ^{

        // ... Do background stuff ...
    });

    dispatch_async(loadQueue, ^{

        dispatch_async(dispatch_get_main_queue(), ^{

            loadCompletion();
        });
    });

    dispatch_release(loadQueue);
}

loadCompletionこのメソッドの呼び出し元が存在しなくなった場合にのみ呼び出される可能性があるため、ブロックをコピーする必要がありますか?それともこのように問題ありませんか?

4

4 に答える 4

3

別のブロック内でブロック パラメーターを参照すると、暗黙的にヒープにコピーされるため、明示的に行う必要はありません。

于 2013-02-03T16:49:10.340 に答える
3

dispatch_async()直接渡されたブロックで正しいことを行うことに頼ることができます。また、ブロックがコピーされると、それによってキャプチャされたブロックがコピーされる場合もあります。loadCompletionは内部ブロックから参照され、 で宣言されていないため、__blockキャプチャされます。言い換えれば、あなたは元気です。

于 2013-02-03T16:49:33.573 に答える
0

このままでいいです。ただし、コードに 1 つの変更を加える必要があります。

dispatch_async(loadQueue, ^{
    dispatch_async(dispatch_get_main_queue(), ^{
        if (loadCompletion) {
            loadCompletion();       
        }
    });
});

自分でテストできます。パラメーターなしでメソッドを呼び出すと ( [instance loadStoreWithCompletion:nil];)、コードのバージョンでは、完了ハンドラーの呼び出し時にアプリがクラッシュします。ブロック チェックは、ブロックが (もう) 存在しない場合のクラッシュを防ぎます。

于 2013-02-03T16:43:16.803 に答える
0

ブロックは呼び出し元によってスタックに割り当てられます。これは、スコープ外になると、呼び出しがエラーにつながることを意味します。

後でそれらを使用する場合は、常にそれらをヒープにコピーする必要があります (非同期で発生するコールバックのように)。

  • 直接呼び出すことによって[block copy]
  • として宣言されているプロパティにそれらを格納することによってcopy

それらはスタック上にある可能性があるため、保持または解放が常に機能するとは限らないことに注意してください。

于 2013-02-03T16:43:38.480 に答える