Escaping closure is een closure die "wegglijdt" uit de scope van de aanroepende functie (bijvoorbeeld, het wordt opgeslagen voor asynchrone uitvoering).
Standaard accepteren functies in Swift non-escaping closures: de closure wordt uitgevoerd binnen de aanroep van de functie.
Om expliciet aan te geven dat een closure escaping is, wordt het sleutelwoord @escaping gebruikt:
func asyncTask(completion: @escaping () -> Void) { DispatchQueue.main.async { completion() } }
Belangrijke verschillen:
[weak self] of [unowned self] aangeven om geheugenlekken (retain cycle) te voorkomen.Moet je altijd @escaping schrijven voor closures die worden doorgegeven als parameters van de functierit DispatchQueue.async?
— Ja. Omdat DispatchQueue.async de closure opslaat tot het moment van uitvoering, wordt de closure escaping.
Voorbeeld:
func foo(action: () -> Void) { DispatchQueue.main.async { action() // Compileert niet: closure moet escaping zijn. } } // Nodig: func bar(action: @escaping () -> Void) { ... }
Verhaal
De controller maakte een sterke referentie naar self binnen een escaping closure (bijvoorbeeld een netwerkverzoek). De controller werd niet vrijgegeven na vertrek van het scherm — sterke retain cycle. Oplossing: gebruik [weak self] of [unowned self].
Verhaal
De functie gaf een closure door aan DispatchQueue.async, maar merkte deze niet aan als escaping. Het project compileerde niet, fouten waren moeilijk te vinden door de geneste functies.
Verhaal
Binnen de closure werd verwezen naar een object dat al was gedeïnitieerd op het moment van aanroepen van de closure (gebruikte [unowned self]). Resultaat — runtime crash. Oplossing: gebruik [weak self] en controleer op nil.