Jaebi의 Binary는 호남선

Swift - 문법 (Property Wrappers) 본문

Swift

Swift - 문법 (Property Wrappers)

jaebijae 2024. 6. 12. 05:27

목차

    Property Wrappers

    • 배경 → 상태를 나타내는 property들을 처리할 때 수정될때마다 trigger되는 logic이 있는경우가 많음
      • ex) 새 값을 검증, 변환, 또는 listen등을 수행 할 수 있음
    • 이미 정의된 property가 있을 때, 이 property를 감싸서 computed-property로 만든 새로운 Wrapper 프로퍼티
    @propertyWrapper struct Capitalized {
        var wrappedValue: String {
            didSet { wrappedValue = wrappedValue.capitalized }
        }
        init(wrappedValue: String) {
            // didSet 실행은 초기화가 완료된 이후에만 트리거 됨
            self.wrappedValue = wrappedValue.capitalized
        }
    }
    • `propertyWrapper`내에는 `wrappedValue` 라는 Property가 존재
      • stored-property로 사용 (didSet) → 내부에서 단순 처리만 사용
      • computed-property로 사용 (get, set) → 내부에서 복잡한 작업을 시도
    // ex2) computed-property로 사용하여 get, set 이용
    @propertyWrapper
    struct AccessToken {
      private enum Key {
        static let accessToken = "accessToken"
      }
      private let storage = UserDefaults.standard
      var wrappedValue: String {
        get { self.storage.string(forKey: Key.accessToken) ?? "defaultValue" }
        set { self.storage.set(newValue, forKey: Key.accessToken) }
      }
    }
    // 사용
    class ViewController: UIViewController {
      @AccessToken var accessToken // <- 주의: computedProperty로 구현된 PropertyWrapper는 초기화 x
      override func viewDidLoad() {
        super.viewDidLoad()
        print(self.accessToken) // "defaultValue"
      }
    }
    • 특별한 기능을 갖는 속성을 정의 하는데 사용
    • projectedValue
      • propertyWrapper 내부에서 다른 값을 정의하여 사용하는쪽에서 `$` 키워드로 해당 값에 접근 하는 기능
      • propertyWrapper에서 부가적인 property 접근에 사용
    • wrappedValue
      • 사용하는쪽에서 선언할 때 그 변수값에 대한 wrapping된 값에 접근
    • projectedValue 사용
      • 정의: propertyWrapper 내부의 projectedValue를 정의
      • 사용: `$` 로 선언한 변수 명으로 접근
    @propertyWrapper
    struct Wrapper<T> {
        var wrappedValue: T
        var projectedValue: Wrapper<T> { return self }
        func foo() { print("Foo") }
    }
    struct HasWrapper {
        @Wrapper var x = 0
        func foo() {
            print(x) // `wrappedValue`
            print(_x) // wrapper type itself
            print($x) // `projectedValue`
        }
    }