Escaping Closure in Swift
In Swift, an escaping closure is a closure that outlives the function it’s passed to. The term “escaping” means the closure can “escape” the scope of the function it was passed to and be executed later.
Why Escaping Closures are Important
When you pass a closure to a function:
- By default, Swift assumes the closure is non-escaping, meaning it will be executed within the function’s body and won’t persist after the function returns
- If the closure needs to be stored for later execution (after the function returns), you must mark it as
@escaping
When to Use @escaping
You need to mark a closure parameter as @escaping
when the closure:
- Is stored in a property, variable, or constant outside the function
- Is passed as an argument to another function that stores it
- Will be executed after the function returns
Common Use Cases
Escaping closures are commonly used for:
- Asynchronous operations (like network calls)
- Completion handlers
- Delegation patterns
- Storage of callback functions
Syntax Example
// Non-escaping closure (default)
func performOperation(completion: () -> Void) {
// The closure must be called before this function returns
completion()
}
// Escaping closure
func performAsyncOperation(completion: @escaping () -> Void) {
// Store the closure for later execution
DispatchQueue.main.async {
completion() // Called after the function returns
}
}
Memory Management Implications
Escaping closures require special attention to memory management:
- They can create reference cycles (strong reference cycles or retain cycles)
- Within an escaping closure, you need to explicitly use
self
(instead of implicit self) - Often you’ll use
[weak self]
or[unowned self]
to avoid memory leaks
Thanks for reading!