Capturing from the enclosing scope
Finally, let’s return to the defining characteristic of a closure: it can access the variables and constants from within its own scope.
Note: Recall that scope defines the range in which an entity (variable, constant, etc) is accessible. You saw a new scope introduced with if- statements. Closures also introduce a new scope and inherit all entities visible to the scope in which it is defined.
For example, take the following closure:
var counter = 0
let incrementCounter = { counter += 1
}
incrementCounter is rather simple: It increments the counter variable. The counter variable is defined outside of the closure. The closure is able to access the variable because the closure is defined in the same scope as the variable. The closure is said to capture the counter variable. Any changes it makes to the variable are visible both inside and outside the closure.
Let’s say you call the closure five times, like so:
incrementCounter() incrementCounter() incrementCounter() incrementCounter() incrementCounter()
After these five calls, counter will equal 5.
The fact that closures can be used to capture variables from the enclosing scope can be extremely useful. For example, you could write the following function:
func countingClosure() -> (() -> Int) { var counter = 0
let incrementCounter: () -> Int = { counter += 1
return counter
}
return incrementCounter
}
This function takes no parameters and returns a closure. The closure it returns takes no parameters and returns an Int.
The closure returned from this function will increment its internal counter each time it is called. Each time you call this function you get a different counter.
For example, this could be used like so:
let counter1 = countingClosure() let counter2 = countingClosure()
The two counters created by the function are mutually exclusive and count independently. Neat!