WWDC24 SALE: Save 50% on all my Swift books and bundles! >>


You've met integers, strings, doubles, floats, Booleans, arrays, dictionaries, structs and classes so far, but there's another type of data that is used extensively in Swift, and it's called a closure. These are complicated, but they are so powerful and expressive that they are used pervasively in Swift, so you won't get very far without understanding them.

A closure can be thought of as a variable that holds code. So, where an integer holds "0" or "500", a closure holds lines of Swift code. Closures also capture the environment where they are created, which means they take a copy of the values that are used inside them.

You never need to design your own closures so don't be afraid if you find the following quite complicated. However, Apple’s frameworks will often ask you to write closures to match their needs, so you at least need to know how they work.

Here’s an example from SwiftUI:

let message = "Button pressed"

Button("Press Me", action: {

Button is one of the many user interface controls we have in SwiftUI, and provides something that user can press on to execute some sort of action.

In this code, creating a button takes two parameters: some text to show as the button’s title, and a closure containing the code to be executed when the button is pressed. I've specified “Press Me” for the first parameter, and for the second I've made the system print a message string.

This method needs to use a closure because SwiftUI won’t run the code until the button is pressed – it will stash the action code away for later on, then call it only when needed. This wouldn't be possible if we just ran our code directly.

The above code also shows how closures capture their environment: I intentionally declared the message constant outside of the closure, then used it inside. Swift detects this, and makes that data available inside the closure too.

Swift's system of automatically capturing a closure's environment is very helpful, but can occasionally trip you up: if object A stores a closure as a property, and that property also references object A, you have something called a retain cycle and you'll have unhappy users. This is a substantially more advanced topic than you need to know right now, so don't worry too much about it just yet.

Trailing closures

As closures are used so frequently, Swift can apply a little syntactic sugar to make your code easier to read. The rule is this: if the last parameters to a method are closures, you can eliminate those parameters and instead provide them as a block of code inside braces. For example, we could convert the previous code to this:

let message = "Button pressed"

Button("Press Me") {

It does make your code shorter and easier to read, so this syntax form – known as trailing closure syntax – is preferred.

A function can have multiple trailing closures if needed, and this is particularly common in SwiftUI. For example, one way to create a button is to provide code to run when it’s pressed as the first closure, then something custom to show inside the button on the screen, like this:

Button {
    print("The button was pressed")
} label: {

That uses an image rather than a simple piece of text, but it could be any kind of SwiftUI user interface control.

Save 50% in my WWDC sale.

SAVE 50% To celebrate WWDC24, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

Unknown user

You are not logged in

Log in or create account

Link copied to your pasteboard.