Sobes.tech
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.