Achtergrond:
defer werd geïntroduceerd in Swift om het beheer van bronnen en het uitvoeren van bewerkingen na het voltooien van een codeblok gemakkelijker te maken, vergelijkbaar met finally in andere talen. Deze constructie helpt duidelijk de stappen van opruiming of afronding van werken met bronnen aan te geven.
Probleem:
Veel beginners denken dat defer de geneste code onmiddellijk uitvoert, zonder altijd het moment van activering correct te begrijpen. Er zijn ook situaties waarin meerdere defer-blokken moeilijk te begrijpen zijn, als je de LIFO-regel (last-in, first-out) niet kent. Mogelijke complicaties met try/catch en vroegtijdig retourneren.
Oplossing:
defer voert de geneste code pas aan het einde van de scope uit, voordat je de huidige functie-blok verlaat, zelfs als de exit eerder plaatsvindt (via return, throw, break, enz.). Meerdere defer worden in omgekeerde volgorde van hun verschijnen uitgevoerd.
Voorbeeldcode:
func readFile() { print("Open bestand") defer { print("Sluit bestand") } print("Lees regel 1") if Bool.random() { print("Vroeg retour!") return } print("Lees regel 2") } readFile() // In de console zal altijd verschijnen: Open bestand, ..., Sluit bestand (aan het einde)
Belangrijkste kenmerken:
Kan defer buiten een functie worden gebruikt?
Nee, defer is alleen toegestaan binnen functies, methoden, initializers en deinitializers. Het kan niet bijvoorbeeld in de globale ruimte van een bestand of binnen een codebron buiten functies worden geplaatst.
Wat gebeurt er met defer als er een exceptie (throw) in het blok is?
defer wordt alsnog uitgevoerd. Dit is een van de voordelen — de bron wordt gegarandeerd vrijgegeven, zelfs in geval van een fout (throw). Zo wordt een veilig patroon voor het vrijgeven van bronnen geïmplementeerd.
In welke volgorde worden meerdere defer uitgevoerd?
Ze worden in omgekeerde volgorde uitgevoerd (LIFO): die defer die later werd verklaard, wordt eerder uitgevoerd.
Voorbeeldcode:
func test() { defer { print("Eerste") } defer { print("Tweede") } print("Binnen") } test() // Dit geeft: "Binnen", "Tweede", "Eerste"
Een functie met meerdere, niet-sequentieel gelegde defer; het opruimen van sommige bronnen vergeten, retouren uit de functie op verschillende plaatsen. Dit leidt tot bronnenlekken en moeilijke debugging van gedrag.
Voordelen: Uniformiteit van code, opruimacties "samengevoegd" op één plek.
Nadelen: Lastig te volgen wat uitgevoerd wordt en in welke volgorde; mogelijke lekken bij logische fouten.
Één defer per belangrijke stap maken, direct daar waar de bron wordt geïnitialiseerd, met opmerkingen. Code-review wordt uitgevoerd.
Voordelen: Gegarandeerde opruiming van bronnen, duidelijke volgorde van acties.
Nadelen: Vereist discipline en aandacht bij het toevoegen van nieuwe bronnen en opruimblokken.