Middle
Explain the difference between escaping and non-escaping closures, and in which cases it is necessary to use @escaping.
sobes.tech AI
Answer from AI
By default, closures are non-escaping.
Non-escaping closure:
- Executed within the function it is passed to.
- Captures variables but releases them after the function ends.
- Does not outlive the function.
func doSomething(completion: () -> Void) {
// Call completion here
completion()
}
Escaping closure:
- Executed after the function it is passed to returns.
- Outlives the function body.
- Can be stored for later execution, such as in another thread or asynchronously.
- Captures variables with strong references, which can lead to retain cycles. Requires explicit
@escaping.
class DataManager {
var completionHandlers: [() -> Void] = []
func addCompletionHandler(handler: @escaping () -> Void) {
completionHandlers.append(handler)
}
func performTasks() {
// Perform tasks...
for handler in completionHandlers {
handler() // Call handlers later
}
}
}
Use of @escaping is necessary in the following cases:
- When a closure is stored in a property of a class or struct.
- When a closure is passed to another thread or asynchronous operation (e.g., network request, GCD, OperationQueue).
- When a closure is used as an event handler or delegate.