Sobes.tech
Middle

Explique la diferencia entre closures de escape y no escape, y en qué casos es necesario usar @escaping.

sobes.tech AI

Respuesta de la IA

Los cierres por defecto son no escapables.

Cierre no escapable:

  • Se ejecuta en el cuerpo de la función a la que se pasa.
  • Captura variables, pero las libera después de que la función termina.
  • No sobrevive a la función.
func doSomething(completion: () -> Void) {
    // Llamada a completion aquí
    completion() 
}

Cierre escapable:

  • Se ejecuta después de que la función a la que se pasa retorna.
  • Sobrevive al cuerpo de la función.
  • Puede ser almacenado para su ejecución posterior, por ejemplo, en otro hilo o de forma asíncrona.
  • Captura variables, manteniendo referencias fuertes, lo que puede llevar a ciclos de referencias fuertes (retains cycles). Requiere la declaración explícita @escaping.
class DataManager {
    var completionHandlers: [() -> Void] = []

    func addCompletionHandler(handler: @escaping () -> Void) {
        completionHandlers.append(handler)
    }

    func performTasks() {
        // Realización de tareas...
        for handler in completionHandlers {
            handler() // Llamada a los manejadores más tarde
        }
    }
}

El uso de @escaping es necesario en los siguientes casos:

  • Cuando la clausura se almacena en una propiedad de una clase o estructura.
  • Cuando la clausura se pasa a otro hilo o operación asíncrona (por ejemplo, solicitud de red, GCD, OperationQueue).
  • Cuando la clausura se usa como manejador de eventos o delegado.