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

Jor*_*n H 7 closures in-app-purchase ios swift

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

我这样定义它:

typealias RequestProductsCompletionHandler = (success: Bool, products: NSArray) -> Void
Run Code Online (Sandbox Code Playgroud)

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

var completionHandler: RequestProductsCompletionHandler?
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

RequestProductsCompletionHandler _completionHandler;

- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
    _completionHandler = [completionHandler copy];
}
Run Code Online (Sandbox Code Playgroud)

后来它被这样使用:

_completionHandler(YES, skProducts);
_completionHandler = nil;
Run Code Online (Sandbox Code Playgroud)

编辑:我已删除.copy()以防止错误(还必须使NSArray可选,以便我可以将其设置为零以后).我的问题是,它是否会按预期工作而不明确复制它?我不相信它会因为Apple声明闭包是参考类型.这将存储对原始闭包的引用,我不想这样做.如何执行副本?

tsa*_*rir 4

是的。它将按预期工作。

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

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