在 swift 闭包中使用 `[weak self]` 是正确的方法吗?
Is it the right way using `[weak self]` in swift closure?
我总是在 swift 闭包中使用 [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
吗?
你说:
someTask(completion: {[weak self] (result) in
if self == nil {
return
}
//is it safe when reach here?
self!.xxx = yyy
})
不!你没有保留self
,所以理论上在执行闭包的过程中随时可能变成nil
。它可能不会,但 "probably" 还不够好。感叹号总是让人崩溃。
跳弱强之舞,并且跳得正确:
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
}
})
从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()
})
您的模式存在竞争条件。如果 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()
}
有时你需要“弱自强自舞”(前两种选择),但在这里似乎不是这样。这可能就足够了。
人们可能会考虑其他 scenarios/edge 个案例,但这些是基本方法。
我总是在 swift 闭包中使用 [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
吗?
你说:
someTask(completion: {[weak self] (result) in
if self == nil {
return
}
//is it safe when reach here?
self!.xxx = yyy
})
不!你没有保留self
,所以理论上在执行闭包的过程中随时可能变成nil
。它可能不会,但 "probably" 还不够好。感叹号总是让人崩溃。
跳弱强之舞,并且跳得正确:
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
}
})
从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()
})
您的模式存在竞争条件。如果 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() }
有时你需要“弱自强自舞”(前两种选择),但在这里似乎不是这样。这可能就足够了。
人们可能会考虑其他 scenarios/edge 个案例,但这些是基本方法。