Property Wrappers는 속성(예: 검증, 변경 또는 특정 방식으로 저장하는 것)과 관련된 로직을 캡슐화하고 코드 주석을 통해 다양한 속성에 재사용할 수 있도록 하는 메커니즘입니다. 이는 반복적인 코드를 제거하고 가독성을 높이는 데 도움을 줍니다.
Property Wrapper는 @propertyWrapper 주석과 필수 속성 wrappedValue를 구현하는 구조체, 클래스 또는 열거형입니다.
제한 사항 및 세부 사항:
예제: 값의 범위를 자동으로 제한하는 property wrapper(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 // 이제 p.age = 120 p.age = -10 // 이제 p.age = 0
적용된 구조체/클래스 외부에서 원래 property wrapper 객체에 접근하는 방법은 무엇입니까?
답변: 속성 이름 앞에 밑줄(_)을 사용하십시오. 예를 들어, 속성 이름이 age인 경우 property wrapper 객체는 _age로 접근할 수 있습니다:
var p = Person() let wrapper = p._age // 이는 Clamped<Int> 타입입니다.
이야기
UserDefaults를 저장하기 위해 프로젝트에 기본 데이터 유형으로 작동하는 사용자 정의 property wrapper가 구현되었습니다. 참조 유형(class)에서 사용할 때 예기치 않은 메모리 누수가 발생했으며, property wrapper가 객체에 strong reference를 갖고 있어 강력한 순환과 데이터 누수로 이어졌습니다. 오류는 wrapper 내에서 weak/unowned reference로 전환하여 수정되었습니다.
이야기
프로젝트에서 computed 속성에 property wrapper를 적용하려 하였으나, 컴파일러가 오류를 발생시켰습니다: property wrapper는 저장된 속성에만 사용될 수 있습니다. 이 사실을 간과하여 모듈 개발이 2일 지연되었습니다.
이야기
감싸는 구조체를 만들 때 init(wrappedValue:...)를 통한 올바른 초기화 문법을 구현하는 것을 잊었습니다. 그 결과 property wrapper를 통해 기본값을 설정할 수 없게 되었으며, 이는 많은 모델 통합 후에야 발견되었습니다. 아키텍처를 재검토해야 했습니다.