Property Wrappers în Swift: Încapsularea Logicii de Acces cu @propertyWrapper în Swift (iOS & macOS)

Arhitectură & POP Swift 6.0

Ghid complet pentru Property Wrappers în Swift: crearea wrapper-elor custom prin @propertyWrapper, gestionarea wrappedValue și valorilor proiectate cu projectedValue ($), și aplicarea în validări și persistență de date.

Sintaxă Swift
@propertyWrapper struct Clamped<T: Comparable> { var wrappedValue: T; var projectedValue: Bool }

Property Wrappers (adnotarea @propertyWrapper) reprezintă o funcționalitate elegantă introdusă în Swift pentru a extrage și reutiliza logica repetitivă de definire a modului în care o proprietate este stocată, calculată sau validată la citire și scriere. Stau la baza unor adnotări fundamentale din SwiftUI precum @State, @Binding sau @AppStorage.

Anatomia unui Property Wrapper

Fiecare wrapper trebuie să implementeze obligatoriu proprietatea wrappedValue. Opțional, poate defini proprietatea projectedValue, care expune o perspectivă suplimentară asupra proprietății (accesibilă în cod prin prefixul $).

Implementarea unui Wrapper Custom: @Clamped
// Wrapper care limitează o valoare între un minim și un maxim configurabil:
@propertyWrapper
struct Clamped<Value: Comparable> {
    private var valoare: Value
    let minim: Value
    let maxim: Value

    init(wrappedValue: Value, intre interval: ClosedRange<Value>) {
        self.minim = interval.lowerBound
        self.maxim = interval.upperBound
        self.valoare = min(max(wrappedValue, minim), maxim)
    }

    var wrappedValue: Value {
        get { valoare }
        set { valoare = min(max(newValue, minim), maxim) }
    }

    // projectedValue expune un boolean care indică dacă ultima atribuire a atins limita:
    var projectedValue: Bool {
        return valoare == minim || valoare == maxim
    }
}

// Utilizarea wrapper-ului într-o structură:
struct SetariAudio {
    @Clamped(intre: 0...100)
    var volum: Int = 50

    @Clamped(intre: -10...10)
    var balans: Int = 0
}

var audio = SetariAudio()
audio.volum = 150
print(audio.volum)      // Afișează 100 (limitat automat!)
print(audio.$volum)     // Afișează true (projectedValue indică atingerea limitei!)

audio.volum = 75
print(audio.$volum)     // Afișează false

Cazuri Comune de Utilizare Enterprise

  • Validare și Sanitizare Date: Wrapper-e care elimină automat spațiile albe (@Trimmed) sau validează formatul adreselor de email.
  • Persistență Locală: Salvarea transparentă a setărilor în UserDefaults sau Keychain la fiecare mutație.
  • Jurnalizare și Tracing: Înregistrarea accesului la proprietăți sensibile pentru audit de securitate.