Escaping Closure ist ein Closure, das "aus der Sichtbarkeit" der aufrufenden Funktion "entkommt" (z. B. für asynchrone Ausführung gespeichert wird).
Standardmäßig akzeptieren Funktionen in Swift non-escaping Closures: Das Closure wird innerhalb des Funktionsaufrufs ausgeführt.
Um ein escaping ausdrücklich anzugeben, wird das Schlüsselwort @escaping verwendet:
func asyncTask(completion: @escaping () -> Void) { DispatchQueue.main.async { completion() } }
Wesentliche Unterschiede:
[weak self] oder [unowned self] ausdrücklich angeben, um Speicherlecks (retain cycles) zu vermeiden.Muss man immer @escaping für Closures verwenden, die als Parameter in Funktionen übergeben werden, die DispatchQueue.async aufrufen?
— Ja. Da DispatchQueue.async das Closure bis zur Ausführung speichert, wird das Closure escaping.
Beispiel:
func foo(action: () -> Void) { DispatchQueue.main.async { action() // Kompiliert nicht: Closure muss escaping sein. } } // Muss: func bar(action: @escaping () -> Void) { ... }
Geschichte
Der Controller hat eine starke Referenz auf self innerhalb eines escaping Closures erstellt (z. B. bei einer Netzwerkanfrage). Der Controller wurde nicht freigegeben, nachdem er vom Bildschirm verschwunden war — starker retain cycle. Lösung: Verwenden von [weak self] oder [unowned self].
Geschichte
Die Funktion übergab das Closure an DispatchQueue.async, jedoch wurde es nicht als escaping markiert. Das Projekt wurde nicht kompiliert, die Fehler waren aufgrund der Verschachtelung der Funktionen schwer zu finden.
Geschichte
Innerhalb des Closures wurde auf ein Objekt zugegriffen, das zum Zeitpunkt des Aufrufs des Closures bereits deinitialisiert war (verwendeten [unowned self]). In der Folge — Laufzeitfehler. Lösung: Verwenden von [weak self] und Überprüfung auf nil.