{ (params) -> ReturnType in body } defines a closure; when it's the last argument, trailing closure syntax lets it move outside the parentheses (or replace them entirely for a single-closure call), and $0/$1 provide implicit shorthand names for a closure's parameters when they're not named explicitly. Closures capture variables from their enclosing scope BY REFERENCE, not by copying — a captured var's later mutations are visible inside the closure. By default, a closure parameter is assumed non-escaping (used only during the function call itself); marking it @escaping is REQUIRED, and compiler-enforced, the moment the closure might be stored and called after the function has already returned — for instance, as a completion handler for an asynchronous operation.
Trailing closures and shorthand argument names
$0 and $1 refer to the closure's first and second parameters implicitly — no need to write ( a, b ) in explicitly for a short, obvious closure body.
let numbers = [5, 2, 8, 1]
let sorted1 = numbers.sorted(by: { (a, b) -> Bool in a > b }) // full syntax
let sorted2 = numbers.sorted { $0 > $1 } // trailing + shorthand
print(sorted2) // [8, 5, 2, 1]Capturing by reference: a live connection, not a snapshot
increment holds a genuine reference to total, not a frozen copy of its value at creation time — each call sees and updates the SAME captured variable, which is exactly what makes this pattern work as a counter.
func makeCounter() -> () -> Int {
var total = 0
let increment = {
total += 1 // captures 'total' by reference
return total
}
return increment
}
let counter = makeCounter()
print(counter()) // 1
print(counter()) // 2 — 'total' genuinely persisted between calls@escaping: required when a closure outlives the call
Without @escaping, this wouldn't compile at all — storing completion for later use, past the point where fetchData itself has already returned, is exactly the scenario @escaping exists to permit and make explicit.
var savedCompletion: (() -> Void)?
func fetchData(completion: @escaping () -> Void) { // REQUIRED — stored for later, outliving this call
savedCompletion = completion // this line is exactly why @escaping is required
}