我已经阅读了有关何时应该在闭包中使用[weak self]
或 [unowned self]
的StackOverflow的几个讨论。
但是,有什么情况我们不必使用 ,因为当我们在内部明确使用self
时Swift没有显示任何错误或警告关闭。
例如,我们应该在这里使用weak
还是unowned
?
UIView.animate(withDuration: 0.3) {
self.view.alpha = 0.0
}
答案 0 :(得分:6)
如果你的闭合可能导致强参考周期,你需要使用[弱自我]或[无主自我]。
如果您将>> 的属性分配并且您引用自我或自我属性,则会发生这种情况 内部关闭本身。闭包是引用类型,因此基本上相同的规则适用于强引用,就像使用普通类一样。
至于您的示例,不需要[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) />"
}
}
答案 1 :(得分:2)
这有点基于意见,所以我会发表意见:)。
我通常以同步性为基础。如果闭包是Async,则调用close时调用实例可能不再存在,因此应使用[weak self]
。如果闭包是同步的,那么它是不必要的,并且捕获一个强引用就可以了。
这个可以扩展为包含闭包,你可以合理地期望你的实例在被调用时保持有效(例如你的View动画案例),但要注意这是一个假设关闭和你的使用将保持不变,所以它理论上可以在未来的某个时候打破。这种安全性降低,使未来的维护更加困难/危险。
对于像UIView.animate这样已建立且可预测的API,我个人倾向于为了简洁而使用强大的自我,但这是一个你自己需要做的评估,它取决于关于用法。
同样如评论中所述,功能关闭也是如此。将闭包分配给另一个变量的属性有一组不同的问题。
顺便说一下,我采用了弱引用闭包的方法,简单地在我的Type中调用另一个方法,例如。
thing.doSomethingWithAClosure() { [weak self]
self?.doSomething()
}
它简化了逻辑,同时还强制执行更多功能/模块化代码。