Capturing Values
Capturing means a closure remembers and holds onto variables from where it was created, even after that place in the code has finished running.
Syntax
func makeFunction() -> () -> Type {
var captured = initialValue
return {
captured += 1 // closure keeps captured alive
return captured
}
}
Capturing a Variable
A closure automatically captures any variables it uses from its enclosing scope, keeping them alive and accessible even after that scope finishes.
Example: Capturing a Variable
// Define the function `makeIncrementer` taking `incrementAmount` and returning a `() -> Int`
func makeIncrementer(incrementAmount: Int) -> () -> Int {
// Declare a mutable variable `total`, initialized to `0`
var total = 0
// Declare a constant `incrementer` (a `() -> Int`); its value is the closure defined below
let incrementer: () -> Int = {
total += incrementAmount
// Return `total` from this function
return total
}
// Return `incrementer` from this function
return incrementer
}
// Declare a constant `incrementByTwo`, set to `makeIncrementer(incrementAmount: 2)`
let incrementByTwo = makeIncrementer(incrementAmount: 2)
// Print `incrementByTwo()` to the console
print(incrementByTwo())
// Print `incrementByTwo()` to the console
print(incrementByTwo())
// Print `incrementByTwo()` to the console
print(incrementByTwo())
Login to try C/C++/Java/PHP code in the editor
Independent Captures per Closure Instance
Each call that creates a new closure gets its own independent captured storage, so separate closures don't interfere with each other.
Example: Independent Captures per Closure Instance
// Define the function `makeIncrementer` taking `incrementAmount` and returning a `() -> Int`
func makeIncrementer(incrementAmount: Int) -> () -> Int {
// Declare a mutable variable `total`, initialized to `0`
var total = 0
// Return a closure that is defined in the block below
return {
total += incrementAmount
// Return `total` from this function
return total
}
}
// Declare a constant `counterA`, set to `makeIncrementer(incrementAmount: 1)`
let counterA = makeIncrementer(incrementAmount: 1)
// Declare a constant `counterB`, set to `makeIncrementer(incrementAmount: 10)`
let counterB = makeIncrementer(incrementAmount: 10)
// Print `counterA()` to the console
print(counterA())
// Print `counterB()` to the console
print(counterB())
// Print `counterA()` to the console
print(counterA())
Login to try C/C++/Java/PHP code in the editor
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the
view already swaps in the hi_ translation fields (or blanks these
out if untranslated), so this renders correctly for both languages
without a lang_code check here. #}
Common Mistakes
- Assuming a captured variable is copied at the moment of closure creation; in Swift, closures capture references and see later mutations.
- Being surprised that two closures created from the same function share the same captured variable's storage.
- Not realizing capturing a large object in a long-lived closure can keep it alive in memory longer than expected.
Chapter Summary
- A closure captures variables and constants from its surrounding context by reference.
- Because of capturing, a closure can still access and modify a variable after its original scope has ended.
- Multiple closures created in the same context can share the same captured variable.
- This capturing behavior is what makes closures useful for things like counters and callbacks.
🔒
Chapter Quiz — Complete all 6 topics to unlock
0/6 topics done
Complete these topics first: