Swift closures have a powerful feature called "capturing values." This allows closures to access and store values from their surrounding context, even after the original scope has ended.
Value capturing occurs when a closure uses variables or constants from its surrounding scope. The closure "captures" these values, creating a reference to them that persists even when the original scope is no longer active.
When a closure captures a value:
func makeIncrementer(incrementAmount: Int) -> () -> Int {
var total = 0
let incrementer: () -> Int = {
total += incrementAmount
return total
}
return incrementer
}
let incrementByTen = makeIncrementer(incrementAmount: 10)
print(incrementByTen()) // Output: 10
print(incrementByTen()) // Output: 20
In this example, the incrementer
closure captures both total
and incrementAmount
. It can access and modify these values even after makeIncrementer
has finished executing.
When capturing reference types, be cautious of creating strong reference cycles. Use capture lists to define weak or unowned references when necessary.
func counter() -> (increment: () -> Int, decrement: () -> Int) {
var count = 0
return (
increment: { count += 1; return count },
decrement: { count -= 1; return count }
)
}
let operations = counter()
print(operations.increment()) // Output: 1
print(operations.increment()) // Output: 2
print(operations.decrement()) // Output: 1
This example demonstrates how multiple closures can capture and modify the same value. Both increment
and decrement
closures capture and modify the count
variable.
To deepen your understanding of capturing values in Swift, explore these related topics:
Mastering value capturing in Swift allows you to create more powerful and flexible closures, enhancing your ability to write efficient and expressive code.