如果我在传递给它的方法中使用它,是否需要复制块?

时间:2013-02-03 16:38:39

标签: iphone objective-c objective-c-blocks grand-central-dispatch

我有一个类似的方法:

- (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 个答案:

答案 0 :(得分:3)

在另一个块中引用块参数的行为将导致它被隐式复制到堆中,因此您不需要显式地这样做。

答案 1 :(得分:3)

你可以依靠dispatch_async()对直接传递给它的块做正确的事。还有一种情况是,当复制块时,它会复制由它捕获的任何块。由于loadCompletion由内部块引用,并且未使用__block声明,因此会捕获它。换句话说,你很好。

答案 2 :(得分:0)

这样很好。但是您应该对代码进行一次更改:

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

您可以自己测试一下。如果您在没有任何参数([instance loadStoreWithCompletion:nil];)的情况下调用该方法,则在您的代码版本中,应用程序将在调用完成处理程序时崩溃。块检查将防止在块不存在的情况下发生任何崩溃。

答案 3 :(得分:0)

调用者在堆栈上分配块,这意味着一旦超出范围,调用就会导致错误。

当您打算稍后使用它们时(例如在异步发生的回调中),您应该始终将它们复制到堆中,您可以这样做

  • 直接调用[block copy]
  • 将它们存储在声明为copy
  • 的属性中

请注意保留它们或释放它们并不总是有效,因为它们可能处于堆叠状态。