ProgrammatieiOS ontwikkelaar

Leg de werking van closures in Swift uit: het verschil met functies, kenmerken van het vastleggen van variabelen, mogelijke problemen bij onjuist gebruik.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

Closures in Swift zijn zelfstandige codeblokken die verwijzingen naar variabelen en constanten uit de omringende context kunnen vastleggen en opslaan. Ze maken het mogelijk om callbacks te organiseren, asynchrone verwerking uit te voeren en het uitvoeren van code als waarden van variabelen op te slaan.

Verschillen met functies

  • Closures kunnen variabelen uit de externe scope vastleggen.
  • Hebben een compacter syntax.
  • Kunnen als waarden worden doorgegeven.

Voorbeeld van een closure:

var counter = 0 let incrementer: () -> Void = { counter += 1 } incrementer() print(counter) // 1

Kenmerken van vastleggen

  • Standaard worden variabelen vastgelegd strong (door een sterke referentie).
  • Je kunt expliciet de vastlegregels definiëren via de capture list ([weak self], [unowned self]).

Problemen

  • Het belangrijkste probleem is mogelijke retain cycles bij het vastleggen van self binnen de closure.
  • In meerdaagse code kan het onopgemerkt verouderde waarden van variabelen vastleggen.

Strikvragen

Wat is het verschil tussen strong-capture en het gebruik van [weak self] of [unowned self] in de capture list van een closure? Wat zijn de gevolgen?

Antwoord: Als je [weak self] of [unowned self] niet opgeeft, zal de closure self standaard vastleggen door een sterke referentie, wat leidt tot een retain cycle als de closure en self naar elkaar verwijzen. [weak self] legt self vast via een zwakke referentie (optioneel), [unowned self] via een ongereguleerd (non-optioneel) verwijzing. Onjuiste keuzes of het ontbreken van een capture list leidt tot geheugenlekken of crashes.

class Test { var closure: (() -> Void)? func setup() { closure = { [weak self] in self?.doWork() } } func doWork() { ... } }

Voorbeelden van echte fouten door gebrek aan kennis van de details van het onderwerp


Verhaal

Een programmeur gebruikte geen capture list in een closure binnen UIViewController, die een asynchrone gegevenslading opstartte. Dit resulteerde in het niet vrijgeven van de controller en zijn view, wat leidde tot een geheugenlek na sluiting (dismiss). Analyse van de infrastructuur toonde honderden "vastgehouden" controllers in het geheugen aan.


Verhaal

De closure legde self vast met [unowned self], maar de levenscyclus van self eindigde eerder dan die van de closure. Dit leidde tot een crash bij de toegang tot een al vrijgegeven object — de applicatie viel uit bij het werken met self binnen de closure.


Verhaal

In een project werden binnen een geneste closure twee variabelen vastgelegd: één als strong, de andere als weak. Het bleek dat de weak-referentie te vroeg werd genegeerd, en de gegevens die nodig waren voor het functioneren van de closure gingen verloren — de bug manifesteerde zich alleen tijdens een stress-test onder belasting in een multithread omgeving.