如何存储Closure完成处理程序以便稍后调用?

时间:2014-09-05 21:09:42

标签: ios swift in-app-purchase closures

我正在努力将此In-App Purchase tutorial转换为Swift,并遇到了一个试图保存完成处理程序的问题。我们需要存储这个完成处理程序,以便以后可以调用它。我无法弄清楚如何从参数中存储闭包的副本。具体来说,我相信我需要复制它,但Xcode声明这个对象没有复制功能。

我已经定义了它:

typealias RequestProductsCompletionHandler = (success: Bool, products: NSArray) -> Void

这里我为它声明了一个属性:

var completionHandler: RequestProductsCompletionHandler?

然后我需要将传入的完成处理程序存储到我的属性中:

func requestProductsWithCompletionHandler(completionBlock: RequestProductsCompletionHandler) -> Void {
    //self.completionHandler = completionBlock.copy() //problem: RequestProductsCompletionHandler does not have a member named copy
}

这是在Obj-C教程中完成的:

typedef void (^RequestProductsCompletionHandler)(BOOL success, NSArray * products);

RequestProductsCompletionHandler _completionHandler;

- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
    _completionHandler = [completionHandler copy];
}

后来就像这样使用了:

_completionHandler(YES, skProducts);
_completionHandler = nil;
编辑:我已删除.copy()以防止错误(还必须使NSArray可选,以便我可以将其设置为nil以后)。我的问题是,它是否会按预期工作而不明确复制它?我不相信它会因为Apple stated closures are reference types这将存储我不想做的原始封闭的引用。如何执行副本?

1 个答案:

答案 0 :(得分:4)

是。它将按预期工作。

每当你调用requestProductsWithCompletionHandler时,你都会创建一个闭包并将其传递给该函数。 正如您所提到的,当您设置completionHandler时,实际上将其设置为对给定闭包的引用。

在Objective C中,要将块存储为ivar,您必须复制块。这是因为一个块首先驻留在定义它的堆栈内存中。并将副本移动到堆内存中以便可以使用

相关问题