Chapters

Hide chapters

Swift Cookbook

Live Edition · Multiplatform · Swift · Editor agnostic

Swift Autoclosures
Written by Team Kodeco

To understand Swift autoclosures, let’s start by reviewing a detail about closures in Swift.

In Swift, a closure isn’t evaluated until it’s called. This can be very useful in some cases, such as when a closure needs to do some time-intensive work.

Let’s review the syntax of how you can pass a closure to a function in Swift:

import Foundation

func delayedPrint(message: String, delay: Double, closure: @escaping () -> Void) {
  DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
    closure()
  }
}

print("Start!")
delayedPrint(message: "Hello, World!", delay: 2) {
  print("Hello, World!")
}
// Output: Start!
// 2 Seconds Later: Hello, World!

In this example, the closure isn’t called until after 2 second delay.

Autoclosures allow you to simplify the syntax of using closures like this, increasing the readability of your code. The @autoclosure attribute automatically generates a closure for you, allowing you to pass an expression as an argument rather than a closure.

With @autoclosure, you could simplify the previous example as follows:

import Foundation

func delayedPrint(message: String, delay: Double, closure: @escaping @autoclosure () -> Void) {
  DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
    closure()
  }
}

print("Start!")
delayedPrint(message: "Hello, World!", delay: 2, closure: print("Hello, World!"))
// Output: Start!
// 2 Seconds Later: Hello, World!

Autoclosures are used in some Swift APIs, such as the assert(condition:message:file:line:) function. This accepts an autoclosure for both its condition and message parameters. The condition parameter is only evaluated in debug builds and the message parameter is only evaluated if the condition is false.

In the case of Swift asserts, autoclosures are useful because the evaluation of the condition is delayed (to never in this case!), and assertions are able to be more readable.

© 2024 Kodeco Inc.