Closures en Swift: sintaxis, trailing closure, @escaping y captura de valores

Cuando la closure es el último argumento puede escribirse fuera de los paréntesis. Si además es el único argumento, los paréntesis desaparecen:

let cuadrados = numeros.map { $0 * $0 }
print(cuadrados)  // [9, 1, 16, 1, 25, 81]

// Múltiples trailing closures (Swift 5.3+)
UIView.animate(withDuration: 0.3) {
    vista.alpha = 0
} completion: { _ in
    vista.removeFromSuperview()
}

Captura de valores

Las closures capturan las variables del entorno por referencia. Esto les permite acumular estado entre llamadas:

func makeContador() -> () -> Int {
    var count = 0
    return { count += 1; return count }
}
let c = makeContador()
print(c())  // 1
print(c())  // 2
print(c())  // 3

@escaping y capture list

Una closure que vive más que la función que la recibe se marca con @escaping. Para evitar retain cycles se usa una capture list con [weak self]:

class ViewModel {
    var datos: [String] = []

    func cargar(completion: @escaping ([String]) -> Void) {
        DispatchQueue.global().async {
            completion(["a", "b", "c"])
        }
    }

    func inicio() {
        cargar { [weak self] items in
            self?.datos = items  // weak evita retain cycle
        }
    }
}

@autoclosure: evaluación perezosa

func log(_ msg: @autoclosure () -> String) {
    #if DEBUG
print(msg())  // solo se evalúa en modo DEBUG
    #endif
}
log("Estado: (calcularEstadoComplejo())")

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP