Labs ICT
โญ Pro Login

Closures

Anonymous functions and trailing syntax.

Closures in Swift

Closures are self-contained blocks of functionality that can be passed around and used in your code. You can think of them as anonymous functions โ€” functions without a name. Closures are everywhere in Swift, from sorting arrays to handling button taps.

// A simple closure assigned to a variable
let greet = { (name: String) -> String in
    return "Hello, \(name)!"
}

print(greet("Alice")) // Hello, Alice!
Try it Yourself ->

Closure Syntax

The full closure syntax looks like this: { (parameters) -> ReturnType in code }. The in keyword separates the parameter/return type declaration from the body of the closure. As you get more comfortable, you'll learn to simplify this syntax considerably.

let multiply = { (a: Int, b: Int) -> Int in
    return a * b
}

let product = multiply(4, 5)
print(product) // 20
Try it Yourself ->

Trailing Closure Syntax

When the last argument to a function is a closure, you can write it as a trailing closure โ€” placing it outside the function parentheses. This makes your code read more naturally, especially with long closure bodies.

let numbers = [5, 3, 1, 4, 2]

// Using trailing closure syntax
let sorted = numbers.sorted { a, b in
    return a < b
}

print(sorted) // [1, 2, 3, 4, 5]
Try it Yourself ->

Shorthand Argument Names

Swift provides shorthand names for closure arguments โ€” $0 refers to the first argument, $1 to the second, and so on. You can drop the parameter list and the in keyword entirely, making closures incredibly concise.

let numbers = [5, 3, 1, 4, 2]

// Using shorthand argument names
let sorted = numbers.sorted { $0 < $1 }
print(sorted) // [1, 2, 3, 4, 5]

// Even shorter with operator function
let sorted2 = numbers.sorted(by: <)
print(sorted2) // [1, 2, 3, 4, 5]
Try it Yourself ->

Capturing Variables

Closures can capture and store references to variables from the surrounding scope. This means the closure keeps those variables alive even after the original scope has finished executing. This is powerful for creating stateful closures.

func makeCounter() -> () -> Int {
    var count = 0
    return {
        count += 1
        return count
    }
}

let counter = makeCounter()
print(counter()) // 1
print(counter()) // 2
print(counter()) // 3
Try it Yourself ->

Closures in Swift APIs

You'll use closures constantly in Swift. Array methods like map, filter, and reduce all take closures as arguments. They're also used for completion handlers, sorting, and responding to events. Mastering closures is essential for writing idiomatic Swift.

let names = ["Alice", "Bob", "Charlie", "Diana"]

// Filter names longer than 3 characters
let longNames = names.filter { $0.count > 3 }
print(longNames) // ["Alice", "Charlie", "Diana"]

// Transform names to uppercase
let uppercased = names.map { $0.uppercased() }
print(uppercased) // ["ALICE", "BOB", "CHARLIE", "DIANA"]
Try it Yourself ->

๐Ÿงช Quick Quiz

What does $0 represent in a closure?