Swift Closures

Swift Closures

Closures are self-contained blocks of functionality that can be passed around and used in your code.

They are very similar to functions. In fact, global and nested functions in Swift are actually just special types of closures.

Closures are highly used in iOS development for completion handlers, sorting algorithms, and asynchronous network calls.


Basic Closure Syntax

Closures are enclosed within curly braces {}.

They define parameters and a return type inside the braces, separated from the closure body by the in keyword.

Simple Closure Example:

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

print(sayHello("Akash"))

Because the closure is assigned to a variable (sayHello), we can call it just like a normal function.


Passing Closures to Functions

One of the primary uses of closures is passing them as arguments to functions.

For example, the Swift array has a .sorted() method that takes a closure to determine how to sort the elements.

Sorting with a Closure:

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

// Sorting alphabetically let sortedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 < s2 })

print(sortedNames)


Type Inference and Shorthand Syntax

Swift compiler is smart. It can infer the types of the parameters and the return type of the closure.

Furthermore, Swift provides shorthand argument names like $0, $1, $2 to refer to the closure's arguments.

This allows us to dramatically shrink the size of our closure code!

Shorthand Closure Syntax:

let names = ["Chris", "Alex", "Ewa", "Barry"]

// Shrunk down using type inference and shorthand arguments let sortedNames = names.sorted(by: { $0 < $1 })

print(sortedNames)


Trailing Closures

If you need to pass a closure expression to a function as the final argument, you can use "trailing closure" syntax.

A trailing closure is written after the function call's parentheses, which makes the code much cleaner and easier to read.

Trailing Closure Syntax:

let names = ["Chris", "Alex", "Ewa", "Barry"]

// The closure is placed outside the parentheses! let sortedNames = names.sorted { $0 < $1 }

print(sortedNames)


Exercise

What keyword is used inside a closure to separate the parameters/return type from the closure's body?