🎓 A1Learner
🔍
0 of 36 lessons completed

Swift Escaping Closures

An escaping closure keeps running after the function that received it has returned. The @escaping mark on a parameter gives the function permission to store that closure for later.

Stored in a variable

The function stores the closure and returns at once. The last call runs the stored closure after the return.

var saved: (() -> Void)?
func store(_ action: @escaping () -> Void) {
    saved = action
    print("stored")
}
store { print("runs later") }
print("function returned")
saved?()

Stored in an array

Each call appends one closure to the array. The loop runs both stored closures in order.

var handlers: [() -> Void] = []
func addHandler(_ handler: @escaping () -> Void) {
    handlers.append(handler)
}
addHandler { print("first handler") }
addHandler { print("second handler") }
print(handlers.count)
for handler in handlers {
    handler()
}

Storing without the mark fails

This program tries to store a plain closure parameter in an outside variable. The compiler refuses it and reports the first error line below.

var stored: (() -> Void)?
func save(_ c: () -> Void) {
    stored = c
}
save { print("saved") }

Example

var stored: (() -> Void)?
func keep(_ action: @escaping () -> Void) {
    stored = action
}
keep { print("Welcome back") }
print("Signed out")
print("Signed in again")
stored?()

Key points

  • A closure parameter is non-escaping by default.
  • A non-escaping closure must finish its work before the function returns.
  • The @escaping mark lets a function store the closure in a variable or an array.
  • A stored closure runs whenever the program later calls it.
  • Storing a non-escaping closure is a compile error.

In this example, keep stores its escaping closure and returns without running it. The program prints two lines first. The stored closure runs only at the final call and prints Welcome back.

Note

completion handlers for slow work are the classic escaping closure.

Try it Yourself

Edit the code, then press Run.

Running is simulated

Exercise

What does the @escaping mark allow a function to do with a closure?