Swiftorial Logo
Home
Swift Lessons
Tutorials
Learn More
Career
Resources

Advanced Swift - Closures

Introduction to Closures

Closures are self-contained blocks of functionality that can be passed around and used in your code. In Swift, closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables, hence the name "closures".

Basic Syntax

Closures in Swift have a clean, clear syntax. Here’s a simple example of a closure:

let simpleClosure = {
    print("Hello, World!")
}

You can call this closure just like a function:

simpleClosure()
Hello, World!

Closures with Parameters and Return Values

Closures can accept parameters and return values just like functions. Here’s an example:

let greetClosure = { (name: String) -> String in
    return "Hello, \(name)!"
}

let greeting = greetClosure("Alice")
print(greeting)
Hello, Alice!

Shorthand Argument Names

Swift provides shorthand argument names to make closures more concise. Here’s an example:

let multiplyClosure = { $0 * $1 }

let result = multiplyClosure(4, 2)
print(result)
8

Trailing Closures

If a closure is the last argument to a function, it can be written as a trailing closure. This improves readability when the closure is long. Here’s an example:

func performOperation(_ a: Int, _ b: Int, operation: (Int, Int) -> Int) -> Int {
    return operation(a, b)
}

let result = performOperation(4, 2) { $0 + $1 }
print(result)
6

Capturing Values

Closures can capture and store references to variables and constants from the surrounding context. Here’s an example:

func makeIncrementer(incrementAmount: Int) -> () -> Int {
    var total = 0
    let incrementer: () -> Int = {
        total += incrementAmount
        return total
    }
    return incrementer
}

let incrementByTwo = makeIncrementer(incrementAmount: 2)
print(incrementByTwo()) // 2
print(incrementByTwo()) // 4
2
4

Escaping Closures

An escaping closure is a closure that is called after the function it was passed to returns. Here's an example:

var completionHandlers: [() -> Void] = []

func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

someFunctionWithEscapingClosure {
    print("Escaping closure")
}

completionHandlers.first?()
Escaping closure

Autoclosures

An autoclosure is a closure that is automatically created to wrap an expression that is being passed as an argument to a function. Here’s an example:

func performOperation(_ a: @autoclosure () -> Bool) {
    if a() {
        print("Operation succeeded")
    } else {
        print("Operation failed")
    }
}

performOperation(3 > 2)
Operation succeeded