Lesson 43Closures

Trailing Closures

What are Trailing Closures?

When a closure is the last argument to a function, you can write it outside and after the parentheses. This makes code cleaner!

Comparison

Regular

numbers.map({ $0 * 2 })

Trailing

numbers.map { $0 * 2 }

Rules

  • Closure must be the last parameter
  • Write the closure after the closing parenthesis
  • If closure is the only parameter, omit () entirely

Multiple Trailing Closures

Swift 5.3+ allows multiple trailing closures. Label each one after the first!

When to Use

  • Multi-line closures (much cleaner!)
  • Common Swift conventions (map, filter, etc.)
  • When it improves readability
main.swift
// TRAILING CLOSURE SYNTAX
// When a closure is the LAST parameter, you can write it
// AFTER the parentheses!

// REGULAR syntax
let numbers = [1, 2, 3, 4, 5]

let doubled1 = numbers.map({ $0 * 2 })

// TRAILING CLOSURE syntax
let doubled2 = numbers.map { $0 * 2 }

// Both produce: [2, 4, 6, 8, 10]

// WHY USE TRAILING CLOSURES?
// - Cleaner, more readable code
// - Better for multi-line closures
// - Common Swift style

// MULTI-LINE TRAILING CLOSURE
let sorted = numbers.sorted { (a, b) in
    // You can have multiple lines here
    let aIsEven = a % 2 == 0
    let bIsEven = b % 2 == 0
    if aIsEven != bIsEven {
        return aIsEven  // Evens first
    }
    return a < b
}
print(sorted)  // [2, 4, 1, 3, 5]

// WHEN CLOSURE IS ONLY PARAMETER
// Can omit () entirely!
let reversed = numbers.sorted { $0 > $1 }

// MULTIPLE TRAILING CLOSURES (Swift 5.3+)
func animate(duration: Double,
             animations: () -> Void,
             completion: () -> Void) {
    print("Animating for \(duration)s")
    animations()
    completion()
}

// Multiple trailing closures syntax
animate(duration: 0.5) {
    print("Running animations...")
} completion: {
    print("Done!")
}

// REAL-WORLD EXAMPLES

// 1. Array operations
let scores = [85, 92, 78, 95, 88]
let passing = scores.filter { $0 >= 80 }
print(passing)  // [85, 92, 95, 88]

// 2. forEach
scores.forEach { score in
    print("Score: \(score)")
}

// 3. Chaining with trailing closures
let result = numbers
    .filter { $0 > 2 }
    .map { $0 * 10 }
    .reduce(0) { $0 + $1 }
print(result)  // 120 (30 + 40 + 50)

Try It Yourself!

Convert this to trailing closure syntax: array.filter({ $0 > 10 }).map({ $0 * 2 })