有这样的事吗?下面两个有什么区别吗?一个比另一个更“正确”吗?
所有对象都是self
的属性(比如一个视图控制器)并且与self
具有相同的生命周期。我们可以引入一个寿命比self
更短的物体,它将是weak
,但同样的问题也适用。
objectOne.doSomething { [unowned self] in
self.objectTwo.finish()
self.tableView.reloadData()
// self.someDelegate?.didFinishSomething()
}
VS
objectOne.doSomething {
[unowned objectTwo = self.objectTwo,
unowned tableView = self.tableView
// weak someDelegate = self.delegate
] in
objectTwo.finish()
tableView.reloadData()
// someDelegate?.didFinishSomething()
}
Apple在their docs中有这个例子:
lazy var someClosure: () -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
delegate?.doSomething()
}
在这种情况下,delegate
的寿命可能比self
短,但为什么不这样使用呢?
lazy var someClosure: () -> String = {
[unowned self] in
// closure body goes here
self.delegate?.doSomething()
}
是的,有一个重要的区别。对于Apple文档,您提供的代码替代方案:
lazy var someClosure: () -> String = {
[unowned self] in
// closure body goes here
self.delegate?.doSomething()
}
当关闭运行时,将在delegate
上查找当前的self
。
在Apple示例版本中:
lazy var someClosure: () -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
delegate?.doSomething()
}
捕获列表中的弱delegate
var正在复制delegate
上的self
指针,该指针存在于闭包声明时,而不是执行。因此,如果self.delegate
的值在声明闭包后发生变化,并且在闭包运行时不同,那么闭包的Apple版本将具有nil委托(假设因为对旧委托的引用很弱)并且什么都不做。
因此,作为一般规则,在捕获列表([someIdentifier = someProperty]
)中复制值或引用是如何使用在定义闭包时存在的值或引用。而在捕获列表([weak self]
)中声明弱或无主自我然后访问该弱引用({ self?.someProperty }
)上的属性将获得执行闭包时存在的属性值。
[unowned objectOne = self.objectOne]
可能导致的问题之一是lazy var UIViews
和竞争条件:如果你不小心并且从不同的线程调用lazy
init,最终可能会创建两个实例。此外,如果您的superview.addSubview(objectOne)
调用位于lazy
init中,则两个实例都将添加到superview
中,而objectOne
将指向两个实例中的一个。