Swift Tutorial · Closures, Generics and Errors · Lesson 18 of 30
Swift Closures
Closure syntax and its shorthand forms, trailing closures, capturing values, and escaping closures.
Closure syntax
A closure is a function without a name: { (a: Int, b: Int) -> Int in a + b }. Swift lets you shorten it a lot:
types are inferred, a single expression doesn't need return, $0 and $1 name the arguments, and an
operator such as + can stand in for a closure. When a closure is the last argument, it goes after the
parentheses (a trailing closure).
let numbers = [5, 2, 9, 1]
let full = numbers.sorted(by: { (a: Int, b: Int) -> Bool in return a < b })
let short = numbers.sorted { $0 < $1 }
let shortest = numbers.sorted(by: <)
print(full, short, shortest)
let add: (Int, Int) -> Int = { $0 + $1 }
print(add(2, 3))
print(numbers.reduce(0, +))
Output
[1, 2, 5, 9] [1, 2, 5, 9] [1, 2, 5, 9] 5 17
Run this on your computer — see “Get Started” for setup.
Capturing values
Closures capture variables from the surrounding scope and keep them alive. A closure stored for later use
(for example a completion handler) is marked @escaping.
func makeCounter() -> () -> Int {
var count = 0
return {
count += 1 // captured and kept alive
return count
}
}
let next = makeCounter()
print(next(), next(), next())
final class Uploader {
private var handlers: [() -> Void] = []
func onComplete(_ handler: @escaping () -> Void) {
handlers.append(handler) // stored to be called later
}
func finish() { handlers.forEach { $0() } }
}
let uploader = Uploader()
uploader.onComplete { print("upload finished") }
uploader.onComplete { print("cache cleared") }
uploader.finish()
Output
1 2 3 upload finished cache cleared
Run this on your computer — see “Get Started” for setup.
Test yourself
In a closure, what does $0 refer to?
The return valueThe first argumentselfThe closure itself
Show answer
Answer: The first argument