我正在努力将此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。 这将存储我不想做的原始封闭的引用。如何执行副本?
答案 0 :(得分:4)
是。它将按预期工作。
每当你调用requestProductsWithCompletionHandler
时,你都会创建一个闭包并将其传递给该函数。
正如您所提到的,当您设置completionHandler
时,实际上将其设置为对给定闭包的引用。
在Objective C中,要将块存储为ivar,您必须复制块。这是因为一个块首先驻留在定义它的堆栈内存中。并将副本移动到堆内存中以便可以使用