Closures
In Swift, closures are self-contained blocks of functionality that can capture and store references to variables and constants from the surrounding context in which they are defined. Closures are similar to lambdas or anonymous functions in other programming languages. They are often used for tasks like delayed code execution, callbacks, and higher-order functions.
Basic Syntax
The simplest form of a closure is a function without a name.
let simpleClosure = { print("Hello, world!") }
simpleClosure() // Output: "Hello, world!"
Parameters and Return Values
Closures can take parameters and return values just like functions. However, their syntax is different.
let add: (Int, Int) -> Int = { (a, b) in
return a + b
}
let sum = add(3, 2) // sum is 5
Type Inference
Swift can infer the types of parameters and the return type based on the context in which the closure is used. This allows for a more concise syntax.
let add = { (a: Int, b: Int) -> Int in
return a + b
}
let subtract = { (a, b) in a - b }
let multiply: (Int, Int) -> Int = { $0 * $1 }
Shorthand Argument Names
Swift automatically provides shorthand argument names ($0, $1, $2, ...) that you can use to refer to the values of the closure’s arguments.
let multiply = { $0 * $1 }
let result = multiply(3, 4) // result is 12
Capturing Values
Closures can capture and store references to variables and constants from the surrounding context, making it possible to manipulate these values from within the closure.
var incrementBy = 0
let incrementer = { () -> Int in
incrementBy += 1
return incrementBy
}
print(incrementer()) // Output: 1
print(incrementer()) // Output: 2
Escaping Closures
By default, closures are non-escaping, meaning they can't outlive the function they are passed to. If you want to store a closure for later execution, you need to mark it as @escaping.
var storedClosure: (() -> Void)?
func someFunction(escapingClosure: @escaping () -> Void) {
storedClosure = escapingClosure
}
Autoclosures
An autoclosure is a closure that is automatically created to wrap an expression that’s being passed as an argument to a function. It doesn’t take any arguments, and when called, it returns the value of the expression that’s wrapped inside of it.
func logIfTrue(_ predicate: @autoclosure () -> Bool) {
if predicate() {
print("True")
}
}
logIfTrue(2 > 1) // Output: "True"
Closures are a powerful feature in Swift and are widely used in iOS development and other Swift-based platforms. They allow for flexible, functional programming and provide a mechanism for controlling the scope and lifetime of variables and constants.