Sweeper
Sweeper

Reputation: 271875

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

I was writing some code similar to:

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 reports an error at print(foo) that I forgot to capture self, and suggests two fixes.:

  1. print(self.foo), or;

  2. Add a capture list of [self] to the closure: ... handler: { [self] _ in ...

Now, I remember that before Xcode 12/Swift 5.3, it didn't use to do that. It either gives no fixes, or just the first one.

My question is, what's the difference between these two fixes? Do they somehow capture self in a different way?

The Language Guide seems to touch on this a little bit, but doesn't seem to say what the difference between them is.

Upvotes: 3

Views: 186

Answers (1)

Rob
Rob

Reputation: 437672

These two are functionally the same, both explicitly capturing self. The [self] pattern avoids having to litter the closure with repeated self. references if you had multiple property and/or method references. But they both do precisely the same thing, capturing self.

As that document you reference says:

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.

Bottom line, they’re the same thing.


For what it’s worth, the other option is to avoid capturing self altogether. E.g. you might only capture foo:

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

Upvotes: 2

Related Questions