Allow implicit self for weak self captures, after self is unwrapped — SE-0365

彼得潘的 iOS App Neverland
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))"
}
}

--

--

彼得潘的 iOS App Neverland

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com