defer is een speciale constructie in Swift die het mogelijk maakt om een bepaalde codeblok uit te voeren net voordat je de scope van een functie verlaat, ongeacht of we de functie verlaten via een normale return of door een fout (throw). Defer is handig voor het vrijgeven van middelen, het terugdraaien van wijzigingen of het beëindigen van operaties.
Bijzonderheden van het werk:
Voorbeeld:
func testDefer() { print("begin") defer { print("eerste defer") } defer { print("tweede defer") } print("eind") } // Zal weergeven: // begin // eind // tweede defer // eerste defer
Grensgevallen:
Zullen alle defer-blokken in de functie worden uitgevoerd als fatalError binnenin wordt aangeroepen?
Antwoord: Nee, als er een fatalError (of soortgelijke oncontroleerbare crashes) binnen de functie wordt aangeroepen, worden alle uitgestelde blokken via defer niet uitgevoerd. defer garandeert niet dat de code wordt uitgevoerd in gevallen van een noodstop van de applicatie.
Voorbeeld:
func foo() { defer { print("Defer 1") } fatalError("Oops") defer { print("Defer 2") } } foo() // geeft niets weer, er treedt een crash op
Verhaal
In het project werd defer gebruikt voor het sluiten van een bestandshandle. Bij het optreden van een fout gebruikten ze fatalError in plaats van een correcte throw, wat leidde tot een lek van een open bron, omdat defer niet werd uitgevoerd bij een crash.
Verhaal
In een functie waren meerdere defer-instructies, waarvan sommige afhankelijk waren van de toestand van lokale variabelen. De ontwikkelaar verwachtte dat de variabele een specifieke waarde zou hebben, maar deze waarde veranderde in defer door een ander deel van de code, en bij het uitvoeren van defer werd de actuele waarde gebruikt in plaats van de oude waarde, wat leidde tot een bug in het annuleren van een transactie op een verkeerd ID.
Verhaal
In een geneste closure werd een defer-blok geschreven, in de veronderstelling dat het zou worden uitgevoerd bij het verlaten van de externe functie. Als gevolg daarvan werd deze defer uitgevoerd bij het verlaten van de closure, en niet van de hele functie, waardoor de bron te vroeg werd vrijgegeven.