ProgrammatieiOS ontwikkelaar

Wat zijn Property Wrappers in Swift? Hoe werken ze, waarvoor worden ze gebruikt, welke beperkingen en mogelijkheden zijn er? Geef een voorbeeld van het maken en toepassen van een custom property wrapper.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

Property Wrappers zijn een mechanisme waarmee de logica rondom properties (bijvoorbeeld validatie, aanpassing of opslag op een bepaalde manier) kan worden ingekapseld en hergebruikt voor verschillende properties door annotaties in de code. Ze helpen om herhalende code te vermijden en de leesbaarheid te verhogen.

Een Property Wrapper is een structuur, klasse of enum die het property wrapper-protocol implementeert via de annotatie @propertyWrapper en een verplicht property wrappedValue.

Beperkingen en nuances:

  • Property Wrappers kunnen niet worden toegepast op computed properties.
  • De overdracht van argumenten bij het initialiseren van de wrapper kan beperkt zijn.
  • Bij het gebruik van meerdere gewikkelde properties binnen een structuur werkt het alleen correct met value types.

Voorbeeld: Laten we een property wrapper schrijven voor het automatisch beperken van een waardebereik (Clamped).

@propertyWrapper struct Clamped<Value: Comparable> { var value: Value let range: ClosedRange<Value> var wrappedValue: Value { get { value } set { value = min(max(newValue, range.lowerBound), range.upperBound) } } init(wrappedValue initialValue: Value, _ range: ClosedRange<Value>) { self.range = range self.value = min(max(initialValue, range.lowerBound), range.upperBound) } } struct Person { @Clamped(0...120) var age: Int = 25 } var p = Person() p.age = 200 // Nu is p.age = 120 p.age = -10 // Nu is p.age = 0

Misleidende vraag

Welke manier van toegang tot het oorspronkelijke property wrapper-object is beschikbaar buiten de structuur/klasse waar het is toegepast?

Antwoord: Via de naam van de property met een onderstreping (_). Bijvoorbeeld, als de property age heet, kan het property wrapper-object worden verkregen als _age:

var p = Person() let wrapper = p._age // dit is het type Clamped<Int>

Voorbeelden van echte fouten door onbekendheid met de nuances van het onderwerp


Verhaal

In een project voor het opslaan van UserDefaults werd een custom property wrapper geïmplementeerd die werkte met primitieve types. Bij het gebruik ervan voor referentietypes (class) ontstond er een onverwachte geheugenlek - de property wrapper hield een sterke referentie naar het object, wat leidde tot een sterke cyclus en datalek. De fout werd hersteld door over te schakelen naar weak/unowned references binnen de wrapper.


Verhaal

In een project probeerden ze property wrapper toe te passen op computed properties, maar de compiler gaf een foutmelding: property wrapper kan alleen worden gebruikt met stored properties. Dit feit werd over het hoofd gezien, wat de ontwikkeling van de module met 2 dagen vertraagde.


Verhaal

Bij het maken van de wrapperstructuur vergaten ze de juiste initialisatiesyntaxis via init(wrappedValue:...) te implementeren. Als gevolg hiervan konden geen defaultwaarden worden ingesteld via de property wrapper, wat pas aan het licht kwam na de integratie van de wrapper in een groot aantal modellen. De architectuur moest opnieuw worden bekeken.