Capturing More Than `self`

A common pattern when using closures in Swift is to add [weak self] in the captures list to hold a weak reference to self and avoid a retain cycle. This is then often followed by the following:

guard let self = self else { return }

But I often forget that capture lists can capture other variables in the current scope, so I thought I'd highlight some other use cases.

When creating a closure in mutating function of a struct capturing self is not possible:

struct Foo {
var bar: Bool

mutating func createClosure() -> () -> Bool {
return { // Error: Escaping closure captures mutating 'self' parameter
return self.bar
}
}
}

var foo = Foo(bar: true)
let closure = foo.createClosure()
closure()

To work around this you can capture the property:

struct Foo {
var bar: Bool

mutating func createClosure() -> () -> Bool {
return { [bar] in
return bar
}
}
}

var foo = Foo(bar: true)
let closure = foo.createClosure()
closure() // true

Another use case is capturing a variable a time of closure creation, when it can also be useful to rename the variable:

class Foo {
var bar: Bool

init(bar: Bool) { self.bar = bar }

func doSomething() {
let closure = { [weak self, originalBar = bar] in
guard let self = self else { return }

if originalBar != self.bar {
print("Bar has changed")
} else {
print("Bar did not change")
}
}

bar.toggle()

closure()
}
}

let foo = Foo(bar: true)
foo.doSomething()

The above code will print Bar has changed.

To read more in-depth information about closures read the Swift language guide page on closures.