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

Iphone 如果在传递到的方法中使用块,是否需要复制块?,iphone,objective-c,objective-c-blocks,grand-central-dispatch,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 ... });

我有一个类似的方法:

- (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
块,因为只有当此方法的调用者不再存在时才会调用它,或者这样可以吗?

这样可以。但您应该在代码中进行1项更改:

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

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

这样很好。但您应该在代码中进行1项更改:

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

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

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


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

  • 通过直接调用
    [block copy]
  • 通过将它们存储在声明为
    copy

记住,保留或释放它们并不总是有效的,因为它们可能在堆栈上。

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


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

  • 通过直接调用
    [block copy]
  • 通过将它们存储在声明为
    copy

请注意,保留或释放它们并不总是有效的,因为它们可能在堆栈上。

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

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

您可以依靠
dispatch\u async()
对直接传递给它的块执行正确的操作。同样的情况是,当一个块被复制时,它会复制它捕获的任何块。由于内部块引用了
loadCompletion
,并且未使用
\uu块
声明,因此会捕获它。换句话说,您很好。

您可以依靠
dispatch\u async()
对直接传递给它的块执行正确的操作。同样的情况是,当一个块被复制时,它会复制它捕获的任何块。由于内部块引用了
loadCompletion
,并且未使用
\uu块
声明,因此会捕获它。换句话说,您很好。

只有在该块已复制的情况下才能确定。这里的要点是,如果需要处理它,它将被自动处理。只有当该块被复制时才可以确保。这里的要点是,如果需要处理,它将被自动处理。“您应该始终将它们复制到堆中”不,只有当您的函数将其存储在比调用寿命更长的位置时才可以。@newacct:我说得更具体一些,通常块是异步使用的,这就是为什么大多数情况下您需要复制它们的原因。我想如果他们不允许调用,那么你就根本不需要块。但是如果你把它传递给一个函数,这个函数存储块供以后使用,并用它进行异步操作,那么这个函数有责任在必要时复制它。您不需要知道(也不应该关心)被调用函数做了什么来做正确的事情。OP函数不会将块存储在实例变量或函数体中的任何位置。因此,他不需要复制它。他的函数中发生了什么才是最重要的。“您应该始终将它们复制到堆中”不,只有在您的函数将其存储在比调用更久的地方时才可以。@newacct:我说得更具体一些,通常块是异步使用的,这就是为什么大多数情况下您需要复制它们的原因。我想如果他们不允许调用,那么你就根本不需要块。但是如果你把它传递给一个函数,这个函数存储块供以后使用,并用它进行异步操作,那么这个函数有责任在必要时复制它。您不需要知道(也不应该关心)被调用函数做了什么来做正确的事情。OP函数不会将块存储在实例变量或函数体中的任何位置。因此,他不需要复制它。他的职能发生了什么才是最重要的。