[英]Is it the right way using `[weak self]` in swift closure?
I always using [weak self]
in swift closure to prevent reference cycle.我总是在快速关闭中使用[weak self]
来防止引用循环。 Here is the code below, is it the correct way?这是下面的代码,这是正确的方法吗?
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?
})
Weak self does not keep a strong hold on the instance.弱自我不会对实例保持强大的控制。 So when self.doLongTermWork()
, will self
be set to nil
again somewhere else?那么当self.doLongTermWork()
, self
会在其他地方再次设置为nil
吗?
Your pattern has race condition.你的模式有竞争条件。 If self
was deallocated at the exact same time as your completion handler closure was executing, it could crash.如果self
在执行完成处理程序闭包的同时被释放,它可能会崩溃。 As a general rule, avoid using the !
作为一般规则,避免使用!
forced unwrapping operator if you can.如果可以,强制解包运算符。
I'd lean towards the guard
“early exit” pattern (reducing nested braces, making code easier to read).我倾向于guard
“提前退出”模式(减少嵌套大括号,使代码更易于阅读)。 The standard Swift 4.2 solution is:标准的 Swift 4.2 解决方案是:
someTask { [weak self] result in guard let self = self else { return } self.xxx = yyy self.doLongTermWork() self.finish() }
Before Swift 4.2, which implemented SE-0079 , we would have to do something like:在实现SE-0079 的Swift 4.2 之前,我们必须执行以下操作:
someTask { [weak self] result in guard let strongSelf = self else { return } strongSelf.xxx = yyy strongSelf.doLongTermWork() strongSelf.finish() }
You can see why we prefer the Swift 4.2 improvement, as this strongSelf
syntax is inelegant.您可以strongSelf
为什么我们更喜欢 Swift 4.2 的改进,因为这种strongSelf
语法不雅。
The other obvious alternative is just:另一个明显的选择是:
someTask { [weak self] result in self?.xxx = yyy self?.doLongTermWork() self?.finish() }
Sometimes you need the “weak self - strong self dance” (the first two alternatives), but it would not appear to be the case here.有时您需要“弱自强自舞”(前两种选择),但这里似乎并非如此。 This is likely sufficient.这可能就足够了。
There are other scenarios/edge cases that one might contemplate, but these are the basic approaches.人们可能会考虑其他场景/边缘情况,但这些是基本方法。
You said:你说:
someTask(completion: {[weak self] (result) in
if self == nil {
return
}
//is it safe when reach here?
self!.xxx = yyy
})
No!不! You have not retained self
, so in theory it might become nil
at any time during the execution of the closure.你没有保留self
,所以理论上它可能会在闭包执行期间的任何时候变为nil
。 It probably won't, but "probably" is not good enough.它可能不会,但“可能”还不够好。 And exclamation marks are always an invitation to crash.并且感叹号总是一个崩溃的邀请。
Do the weak-strong dance, and do it correctly:做弱强舞,并正确地做:
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
}
})
You can use it like this from Swift 4.2你可以从 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()
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.