您询问的情况不会导致参考周期。
仅当 2 个或更多对象直接或间接具有彼此的指针(或由属性内的块捕获)时,才会发生引用循环:
A->B and B->A (direct)
A->B, B->C, C->A (indirect)
现在不存储为实例属性的闭包会发生什么
通常你可能会看到一个视图控制器调用一些库并提供处理程序块。例如:
// inside some method of view controller
APIWrapper.sharedInstance().callApiWithHandler(handler: {
(finished: Bool) -> Void in
// process result of the action
self.showResults()
}
在这种情况下,您不知道完成此操作需要多长时间。您的区块可能会被提交到私有操作队列中。在此操作完成之前,所有捕获的对象都将保持活动状态。
现在甚至是危险的部分:如果用户按下后退按钮(假设涉及导航控制器)并且当前视图控制器从导航堆栈中弹出,self
即使它不会显示在屏幕上,它也会因为捕获而保持活动状态。
这应该重写为:
// inside some method of view controller
APIWrapper.sharedInstance().callApiWithHandler(handler: {
[weak self]
(finished: Bool) -> Void in
// process result of the action
self?.showResults()
}
存储为其他类的实例属性的闭包
这部分类似:您可能无法控制保持对块的引用的对象的生命周期。
捕获的对象是隐式引用,可能难以调试。
总结一下:使用块时,您应该始终考虑该块将存活多长时间以及它是否会产生循环。weak
使用/捕获对象是一种很好的做法,unowned
除非您有充分的理由不这样做。