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 回答