Allow implicit self for weak self captures, after self is unwrapped — SE-0365
2 min readFeb 18, 2023
從 Xcode 14.3 的 Swift 5.8 開始,Apple 在 SE-0365 推出了貼心的新功能,當 weak self 已經被 unwrapped 後,我們可以在接下來的程式省略 self。
以底下 Timer 的 closure 程式為例,在 Swift 5.8 之前,我們必須使用 self 才能存取 controller 的 property view & label。
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
var timer: Timer?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in
guard let self else { return }
self.view.backgroundColor = UIColor(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1), alpha: 1)
self.label.text = "\(Int.random(in: 1...100))"
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
timer?.invalidate()
}
}
沒有加 self 時會出現錯誤 Reference to property xxx in closure requires explicit use of ‘self’ to make capture semantics explicit。
在 Swift 5.8 不用再寫那麼多 self 了,只要 weak self 被 unwrapped,我們即可在接下來的程式省略 self。
- 寫法1: 使用 guard let 做 unwrap。
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in
guard let self else { return }
view.backgroundColor = UIColor(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1), alpha: 1)
label.text = "\(Int.random(in: 1...100))"
}
- 寫法2: 使用 if let 做 unwrap。
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in
if let self {
view.backgroundColor = UIColor(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1), alpha: 1)
label.text = "\(Int.random(in: 1...100))"
}
}