propertyWrapper란 Swift 5.1에서 도입된 기능 중 하나로, 속성에 대한 접근 및 저장을 캡슐화하고 수정자를 제공하여 코드를 간소화하고 재사용성을 높이는 데 사용됩니다.
@propertyWrapper
struct Doubled<Value: Numeric> {
var value: Value
init(wrappedValue: Value) {
self.value = wrappedValue * 2
}
var wrappedValue: Value {
get { value }
set { value = newValue * 2 }
}
}
struct Number {
@Doubled var value: Int
}
var number = Number(value: 5)
print(number.value) // 10 출력
number.value = 8
print(number.value) // 16 출력
만약 @propertyWrapper 구조체에 init이 없다면 number의 타입이 Value가 아니라 Doubled타입이 된다.
class UserManager {
static var usesTouchID: Bool {
get { return UserDefaults.standard.bool(forKey: "usesTouchID") }
set { UserDefaults.standard.set(newValue, forKey: "usesTouchID") }
}
static var myEmail: String? {
get { return UserDefaults.standard.string(forKey: "myEmail") }
set { UserDefaults.standard.set(newValue, forKey: "myEmail") }
}
static var isLoggedIn: Bool {
get { return UserDefaults.standard.bool(forKey: "isLoggedIn") }
set { UserDefaults.standard.set(newValue, forKey: "isLoggedIn") }
}
}
get/set 구현이 겹치는 부분이 있다. @propertyWrapper를 사용해서 코드를 개선해보자!
@propertyWrapper
struct UserDefault<T> {
let key: String
let defaultValue: T
var wrappedValue: T {
get { UserDefaults.standard.object(forKey: self.key) as? T ?? self.defaultValue }
set { UserDefaults.standard.set(newValue, forKey: self.key) }
}
}
class UserManager {
@UserDefault(key: "usesTouchID", defaultValue: false)
static var usesTouchID: Bool
@UserDefault(key: "myEmail", defaultValue: nil)
static var myEmail: String?
@UserDefault(key: "isLoggedIn", defaultValue: false)
static var isLoggedIn: Bool
}
UserDefaults Property Wrapper의 이니셜라이저를 이용하여 기본값을 지정한다.
기존에 있었던 get/set 같은 보일러 플레이트 코드들 없이 동일한 효과를 낼 수 있다.