我总是在快速关闭中使用[weak self]
来防止引用循环。
这是下面的代码,这是正确的方法吗?
someTask(completion: {[weak self] (result) in
if self == nil {
return
}
//is it safe when reach here?
self!.xxx = yyy
self!.doLongTermWork()
self!.finish() //will crash when self is nil?
})
弱自我并不能完全控制实例。因此,当self.doLongTermWork()
时,self
是否会在其他地方再次设置为nil
?
答案 0 :(得分:2)
您说:
someTask(completion: {[weak self] (result) in
if self == nil {
return
}
//is it safe when reach here?
self!.xxx = yyy
})
不!您尚未保留self
,因此从理论上讲,它可能在执行闭包期间随时变为nil
。可能不会,但是“可能”还不够好。而且,感叹号始终是崩溃的邀请。
做弱而有力的舞蹈,并正确地做
someTask(completion: {[weak self] (result) in
if let self = self { // or let `self` before Swift 4
// here, self is safe, because you made the reference strong again
self.xxx = yyy
}
})
答案 1 :(得分:1)
您的模式具有比赛条件。如果self
在完成处理程序关闭执行的同时被释放,则可能会崩溃。通常,请尽量避免使用!
强制展开运算符。
我倾向于使用guard
“提前退出”模式(减少嵌套的花括号,使代码更易于阅读)。标准的Swift 4.2解决方案是:
someTask { [weak self] result in
guard let self = self else { return }
self.xxx = yyy
self.doLongTermWork()
self.finish()
}
在实现SE-0079的Swift 4.2之前,我们必须做类似的事情:
someTask { [weak self] result in
guard let strongSelf = self else { return }
strongSelf.xxx = yyy
strongSelf.doLongTermWork()
strongSelf.finish()
}
您会看到为什么我们偏爱Swift 4.2改进的原因,因为这种strongSelf
语法不雅观。
另一个明显的选择是:
someTask { [weak self] result in
self?.xxx = yyy
self?.doLongTermWork()
self?.finish()
}
有时您需要“弱自我-强自我舞蹈”(前两种选择),但在这里似乎并非如此。这可能就足够了。
还有其他可能需要考虑的场景/边缘情况,但这是基本的方法。
答案 2 :(得分:0)
您可以在Swift 4.2中像这样使用它
someTask(completion: {[weak self] (result) in
guard let self == self { return }
//it safe when reach here always
self.xxx = yyy
self.doLongTermWork()
self.finish()
})