๐ŸŽ“ A1Learner
๐Ÿ”
0 of 36 lessons completed

Swift Capture Lists

A capture list names the values a closure freezes when it is created. The list sits in square brackets at the very start of the closure body.

A frozen value

The capture list copies counter while it still holds 10. The later change to 99 never reaches the closure.

var counter = 10
let frozen = { [counter] in print(counter) }
counter = 99
frozen()

The live value without a list

This closure has no capture list, so it reads counter at call time. The same change to 99 shows up in the print.

var counter = 10
let live = { print(counter) }
counter = 99
live()

A weak reference to an object

The closure captures the bell weakly, so the closure does not keep the object alive. After the bell is gone, the closure prints its fallback word.

class Bell {
    var sound = "ding"
    func makeRinger() -> () -> Void {
        return { [weak self] in
            print(self?.sound ?? "silent")
        }
    }
}
var bell: Bell? = Bell()
let ring = bell?.makeRinger()
ring?()
bell = nil
ring?()

Example

var word = "hello"
let frozen = { [word] in print(word) }
word = "goodbye"
frozen()
print(word)

Key points

  • A closure without a capture list reads the live value of an outside variable.
  • A capture list copies the named value at the moment the closure is created.
  • Later changes to the original variable do not reach a frozen copy.
  • The frozen name works inside the closure like a constant.
  • A capture list can also hold a weak reference to an object.

In this example, the capture list freezes the word hello when the closure is created. The variable then changes to goodbye. The closure still prints the frozen hello, and the last print shows the live variable as goodbye.

Note

a weak reference does not keep the object alive.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

A closure captures [counter] when counter is 10, and counter later becomes 99. What does the closure print for counter?