Labs ICT
โญ Pro Login

Closures

Anonymous functions and trailing syntax.

3 min read | Swift Tutorial
โญ

Want the full learning experience?

Get structured courses, certificates, projects, and instructor support with LabsICT Pro.

Explore Pro Courses

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!

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

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]

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]

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

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"]

๐Ÿงช Quick Quiz

What does $0 represent in a closure?