Swift 프로퍼티 래퍼
프로퍼티 래퍼 이해하기
프로퍼티 래퍼(property wrapper):
- 연산 프로퍼티의 기능(변환 작업, 유효성 검사)을 개별 클래스와 구조체와 분리
- 앱 코드에서 재사용
간단한 예제
<연산 프로퍼티 이용>
struct Address {
private var cityname: String = ""
var city: String {
get { cityname }
set { cityname = newValue.uppercased() }
}
}
var address = Address()
address.city = "London"
print(address.city) // LONDON
도시 이름의 문자열을 대문자로 변환
동일한 작업이 다른 구조체나 클래스에 필요할 때,
<프로퍼티 래퍼 정의>
@propertyWrapper
struct FixCase {
private(set) var value: String = ""
var wrappedValue: String {
get { value }
set { value = newValue.uppercased() }
}
init(wrappedValue initialValue: String) {
self.wrappedValue = initialValue
}
}
@propertyWrapper 지시자를 이용하여 선언
클래스나 구조체 안에 구현
게터와 세터 코드가 포함된 wrappedValue 프로퍼티 포함
초기화 메서드는 선택 사항
<프로퍼티 변수에 적용하여 재사용>
struct Contact {
@FixCase var name: String
@FixCase var city: String
@FixCase var country: String
}
var contact = Contact(name: "John Smith", city: "London", country: "United Kingdom")
print("\(contact.name), \(contact.city), \(contact.country)")
//JOHN SMITH, LONDON, UNITED KINGDOM
동작이 필요한 클래스나 구조체의 선언부에 있는 프로퍼티 선언 앞에 @FixCase 지시자를 붙임
여러 변수와 타입 지원하기
<여러 값을 받는 프로퍼티 래퍼>
@propertyWrapper
struct MinMaxVal {
var value: Int
let max: Int
let min: Int
init(wrappedValue: Int, min: Int, max: Int) {
value = wrappedValue
self.min = min
self.max = max
}
var wrappedValue: Int {
get { return value }
set {
if newValue > max {
value = max
} else if newValue < min {
value = min
} else {
value = newValue
}
}
}
}
init 메서드는 래퍼 값에 추가된 min과 max 값을 받아 구현
struct Demo {
@MinMaxVal(min: 100, max: 200) var value: Int = 100
}
var demo = Demo()
demo.value = 150
print(demo.value) // 150
demo.value = 250
print(demo.value) // 200 최댓값
<동일한 타입의 다른 값과 비교할 수 있는 프로퍼티 래퍼>
- 특정 프로토콜을 따르는 모든 타입과 작업하도록 구현 가능
- 목적은 비교작업 -> Comparable 프로토콜을 따르는 모든 데이터 타입을 지원하도록 수정
@propertyWrapper
struct MinMaxVal<V: Comparable> {
var value: V
let max: V
let min: V
init(wrappedValue: V, min: V, max: V) {
value = wrappedValue
self.min = min
self.max = max
}
var wrappedValue: V {
get { return value }
set {
if newValue > max {
value = max
} else if newValue < min {
value = min
} else {
value = newValue
}
}
}
}
Comparable 프로토콜을 따르는 다른 모든 타입에도 사용가능
struct Demo {
@MinMaxVal(min: "Apple", max: "Orange") var value: String = ""
}
var demo = Demo()
demo.value = "Banana"
print(demo.value) //Banana
demo.value = "Pear"
print(demo.value) //Orange 최댓값
문자열 값이 알파벳 관점에서 최솟값과 최댓값 범위 안에 들어오는지 판단
struct DateDemo {
@MinMaxVal(min: Date(), max: Calendar.current.date(byAdding: .month, value: 1, to: Date())! ) var value: Date = Date()
}
var dateDemo = DateDemo()
print(dateDemo.value) // 디폴트 현재 날짜
dateDemo.value = Calendar.current.date(byAdding: .day, value: 10, to: Date())!
print(dateDemo.value) // 10일 뒤 날짜
dateDemo.value = Calendar.current.date(byAdding: .month, value: 2, to: Date())!
print(dateDemo.value) // 최댓값
Comparable 프로토콜을 따르는 Date 객체를 이용하여 동작