在闭包的捕获列表中使用 "self." 前缀和写 "self" 有什么区别?

What's the difference between using the "self." prefix and writing "self" in the capture list of a closure?

我正在编写一些类似于以下的代码:

class ViewController : UIViewController {
    var foo = "foo"
    override func viewDidLoad() {
        let alert = UIAlertController(title: "", message: "", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "", style: .default, handler: { _ in
            print(foo)
        }))
    }
}

Xcode 报告 print(foo) 处的错误,我忘记捕获 self,并建议 两个 修复。:

  1. print(self.foo), 或;

  2. [self]的捕获列表添加到闭包中:... handler: { [self] _ in ...

现在,我记得在 Xcode 12/Swift 5.3 之前,它并没有这样做。它要么不提供修复,要么只提供第一个修复。

我的问题是,这两个修复有什么区别?他们是否以某种方式以不同的方式捕获 self

Language Guide好像稍微提到了一点,但是好像没有说出它们的区别。

这两个在功能上是相同的,都明确捕获 self。如果您有多个 属性 and/or 方法引用,[self] 模式可以避免在闭包中重复使用 self. 引用。但他们都做同样的事情,捕获 self.

正如您参考的那个文件所说:

Normally, a closure captures variables implicitly by using them in the body of the closure, but in this case you need to be explicit. If you want to capture self, write self explicitly when you use it, or include self in the closure’s capture list.

归根结底,它们是同一回事。


尽管如此,另一种选择是完全避免捕获 self。例如。你可能只会捕获 foo:

alert.addAction(UIAlertAction(title: "", style: .default) { [foo] _ in
    print(foo)
})