Property Wrappers sind ein Mechanismus, der es ermöglicht, die Logik der Arbeit mit Eigenschaften (z. B. Validierung, Änderungen oder Speicherung auf bestimmte Weise) zu kapseln und sie für verschiedene Eigenschaften durch Annotations im Code wiederzuverwenden. Sie helfen, wiederholenden Code zu vermeiden und die Lesbarkeit zu erhöhen.
Ein Property Wrapper ist eine Struktur, Klasse oder Enum, die das Protokoll property wrapper durch die Annotation @propertyWrapper und das obligatorische Attribut wrappedValue implementiert.
Einschränkungen und Feinheiten:
Beispiel: Lassen Sie uns einen Property Wrapper für die automatische Einschränkung des Wertebereichs (Clamped) schreiben.
@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 // Jetzt ist p.age = 120 p.age = -10 // Jetzt ist p.age = 0
Welcher Zugriff auf das ursprüngliche Property Wrapper-Objekt ist außerhalb der Struktur/Klasse, in der es angewendet wurde, verfügbar?
Antwort: Über den Namen der Eigenschaft mit einem Unterstrich (_). Zum Beispiel, wenn die Eigenschaft age heißt, kann das Property Wrapper-Objekt als _age abgerufen werden:
var p = Person() let wrapper = p._age // das ist vom Typ Clamped<Int>
Geschichte
In einem Projekt zur Speicherung von UserDefaults wurde ein benutzerdefinierter Property Wrapper implementiert, der mit primitiven Typen arbeitete. Bei der Verwendung für Referenztypen (Klasse) trat ein unerwarteter Speicherleck auf - der Property Wrapper hielt eine starke Referenz auf das Objekt, was zu einem starken Zyklus und Datenverlust führte. Der Fehler wurde durch den Übergang zu einer schwachen/unowned Referenz innerhalb der Wrapper behoben.
Geschichte
Im Projekt versuchte man, Property Wrapper auf berechnete Eigenschaften anzuwenden, aber der Compiler gab einen Fehler aus: Property Wrapper kann nur mit stored properties verwendet werden. Diese Tatsache wurde übersehen, was die Entwicklung des Moduls um 2 Tage verzögerte.
Geschichte
Bei der Erstellung der Wrapper-Struktur wurde vergessen, die richtige Initialisierungssyntax über init(wrappedValue:...) zu implementieren. Infolgedessen konnten keine Standardwerte über den Property Wrapper festgelegt werden, was erst nach der Integration der Wrapper in einer großen Anzahl von Modellen offensichtlich wurde. Die Architektur musste überarbeitet werden.