在快速关闭中使用"[弱我]"是正确的方法吗?



我总是在快速闭包中使用[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吗?

您的模式具有争用条件。如果在执行完成处理程序闭包的同时解除分配self,则可能会崩溃。作为一般规则,如果可以,请避免使用!强制解包运算符。

  1. 我倾向于guard"提前退出"模式(减少嵌套大括号,使代码更易于阅读)。标准的 Swift 4.2 解决方案是:

    someTask { [weak self] result in
    guard let self = self else { return }
    self.xxx = yyy
    self.doLongTermWork()
    self.finish()
    }
    
  2. 在实现 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语法是不优雅的。

  3. 另一个明显的选择只是:

    someTask { [weak self] result in
    self?.xxx = yyy
    self?.doLongTermWork()
    self?.finish()
    }
    

    有时你需要"弱自我 - 强自我舞蹈"(前两种选择),但这里似乎并非如此。这可能就足够了。

人们可能会考虑其他场景/边缘情况,但这些是基本方法。

你说:

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
}
})

你可以在 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()
})

相关内容

最新更新