什么时候我们不应该使用[weak self]和[unowned self]?
我已经阅读了关于什么时候应该使用[weak self]
或[unowned self]
关闭的几个关于StackOverflow的讨论。什么时候我们不应该使用[weak self]和[unowned self]?
但是,有什么情况我们不需要使用既不是他们,因为当我们只是在闭包中明确使用self
时,Swift不会显示任何错误或警告。
例如,我们应该在这里使用weak
还是unowned
?
UIView.animate(withDuration: 0.3) {
self.view.alpha = 0.0
}
如果闭合会导致强参考周期,则需要使用[weak self]或[unowned self]。
此,如果你分配封盖的自我的属性,可能会发生,你指的自我或自内盖子本身的属性。闭包是引用类型,因此基本上相同的规则适用于强引用,如同使用普通类一样。
至于你的例子,不需要[weak self]
或[unowned self]
,因为你没有把闭包分配给self
引用的类中的变量,所以不会有强的参考周期。
有关更多信息,请查阅Swift编程语言指南的Strong Reference Cycles for Closures部分。下面是从当强参考周期可以通过闭合而引起的所提到的链接的示例:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML:() -> String = {
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
没有[unowned self]
在asHTML
封闭,强大的参考周期将通过分配给asHTML
封闭引起的。将asHTML
更改为以下解决方案可解决此问题:
lazy var asHTML:() -> String = {
[unowned self] in
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
等待,但这2个asHTML var实现有什么区别? – Legonaftik
不小心将'[unowned self]'从正确的实现中排除,现在修复它。 –
这有点意见为主,所以我给我的意见:)
我一般将它基于同步。如果闭包是异步的,则在呼叫闭包机时呼叫实例可能不再存在,因此应使用[weak self]
。如果一个闭包是同步的,这是不必要的,捕获一个强大的参考是好的。
这可以扩大到包括关闭在那里你可以合理地预期,当它被称为(例如,您的观看动画时)的情况下仍然有效,但是请注意,这使得一个假设,即关闭和你对它的使用将保持不变,所以它在理论上可能在未来的某个时候突破。这不太安全,并使未来的维护更加困难/危险。
对于像UIView.animate这样既定且可预测的API,我个人倾向于为了简洁而使用强大的自我,但这是您需要自己做的评估,它取决于使用情况。
同样如注释中所述,函数闭包也是如此。将闭包分配给另一个变量的属性有一组不同的问题。另外,我已经采用弱引用闭包的方法,简单地调用我的类型中的另一种方法,例如,
thing.doSomethingWithAClosure() { [weak self]
self?.doSomething()
}
它简化了逻辑,同时执行更多的功能/模块化代码。
在任何情况下,**没有提及**何时使用**的答案**? –
另请参阅[强封闭循环参考](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html#//apple_ref/doc/uid/TP40014097 -CH20-ID56)Swift编程语言指南的一部分。 –