@propertyWrapper

76 阅读1分钟

1. 在 struct、 enum、类声明时, 在上方添加 @propertyWrapper

@propertyWrapper

struct SmallNumber {
    private var num: Int
    init() {
        num = 0
    }

    var wrappedValue: Int {
        get {
            // 获得的数字不小于6
            return max(num + 1 * 3, 6)
        }
        set {
            // 获得的是偶数
            num = newValue * 2
        }
    }
}

//使用
struct SampleNumber {
    @SmallNumber var num: Int
}

let number = SampleNumber()
print(number.num)

添加 @propertyWrapper 之后, 必须要实现 wrappedValue 计算性属性

2.给该属性赋予一个初始值

需要添加 init(wrappedValue:) 方法

init(wrappedValue: Int) {
    num = wrappedValue
}

// 使用
struct SampleNumber {
    @SmallNumber var num: Int = 0
}

3. wrappedValue 可省略,但是必须为第一个参数

init(wrappedValue: Int, desc: String) {
    num = wrappedValue
    self.desc = desc
}

// 使用
struct SampleNumber {
    @SmallNumber(desc: "small number") var num: Int = 0
}

4. projectedValue 可以声明为常量或者变量, 使用 $ 符号可访问到该值

let projectedValue: Bool

init(wrappedValue: Int, desc: String) {
    num = wrappedValue
    self.desc = desc
    projectedValue = true
}

// 使用
let number = SampleNumber()
print(number.$num)

5. 实际使用案例

@propertyWrapper
struct UserDefault<T> {
    let key: String
    let defaultValue: T

    var wrappedValue: T {
        get {
            UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
        }

        set {
            UserDefaults.standard.set(newValue, forKey: key)
        }
    }
}
  
// 使用
struct GlobalSettings {
    @UserDefault(key: "is_first_load", defaultValue: false)
    static var isFirstLoad
    
    @UserDefault(key: "preference", defaultValue: "basketball")
    static var preference
}