将完成处理程序保存为对象

13

我在想是否有一种方法可以“保存”完成处理程序。

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{

}

- (void)actionHere {
    completionHandler(UIBackgroundFetchResultNewData);
}

我希望将上述结果发送到另一个函数中。

3个回答

33

简而言之

声明一个复制属性(奇怪的语法,我知道...http://fuckingblocksyntax.com/

@property (nonatomic, copy) void (^completionHandler)(UIBackgroundFetchResult fetchResult);

然后像下面这样使用它

- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
    self.completionHandler = completionHandler;
}

- (void)actionHere {
    if (self.completionHandler)
        self.completionHandler(UIBackgroundFetchResultNewData);
}

讨论

在Objective-C中,块是完整的对象,它们有一个重要的区别:默认情况下,它们是在堆栈上分配的。

如果您想保存对块的引用,则必须将其复制到堆上,因为保留堆栈上的块不会防止它在堆栈帧被撤消时丢失。

要复制一个块到堆上,您必须调用Block_Copy()函数。您还可以选择调用copy方法(它将为您调用前面的函数)。

使用copy属性声明一个属性将使编译器自动在通过属性设置器分配对象时插入copy调用。


我们可以保存它的弱引用吗? - Iqbal Khan
有点龟毛,但是在使用完引用后应该将其置为nil,因为你永远不知道actionHere是否会被第二次调用。所以self.completionHandler = nil; - strangetimes

2

块是对象(真正的 ObjC 对象!),唯一重要的是你必须在想要存储它们以供日后使用时复制它们(而不是保留它们)。

因此,你需要进行以下操作之一:

_myCompletionHandler = [completionHandler copy];

或者:

_myCompletionHandler = Block_copy(completionHandler);

抱歉问这么愚蠢的问题,但是在@interface中我应该放什么? - user1413558

2

您需要为您的块声明一个属性。以下是语法:

@property (nonatomic, copy) returnType (^blockName)(parameterTypes);

那么你只需要写 self.blockName = completionHandler

然后在 actionHere 中这样调用它:

self.blockName();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接