如何存储闭包完成处理程序以供以后调用?
Posted
技术标签:
【中文标题】如何存储闭包完成处理程序以供以后调用?【英文标题】:How to store a Closure completion handler to call later? 【发布时间】:2014-09-05 21:09:41 【问题描述】:我正在努力将这个 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】:是的。它将按预期工作。
每当您调用requestProductsWithCompletionHandler
时,您都会创建一个闭包并将其传递给该函数。
正如您所提到的,当您设置 completionHandler
时,您实际上将其设置为对给定闭包的引用。
在 Objective C 中,要将块存储为 ivar,您必须复制一个块。这是因为一个块首先驻留在定义它的堆栈内存中。并将其复制到堆内存中以便可以使用
【讨论】:
我遇到了确切的问题,所以谢谢。在研究答案时,我在 Swift 文档中发现了这个:developer.apple.com/library/ios/documentation/Swift/Conceptual/…。我尝试添加lazy
变量,但它给了我一个错误(变量没有初始化程序)。这会导致引用循环吗?
@coopersita 如您提到的文档中所述,您应该为闭包定义“捕获列表”并指定“自我”是无主的。 [unowned self] in ...
谢谢@tsafrir,我也找到了这个***.com/questions/24320347/…以上是关于如何存储闭包完成处理程序以供以后调用?的主要内容,如果未能解决你的问题,请参考以下文章