Swift-属性包装器

@propertyWrapper

Swift 提供的一种"属性包装器"机制,用来给属性增加统一的逻辑。

它本质上是:

  • 对属性的"读写行为"进行封装
  • 避免重复代码
  • 增强属性能力(缓存、校验、持久化、线程安全等)

基本用法

场景:希望给标题这个属性,提供自动大写逻辑,每次赋值都需要处理

先定义一个属性包装器。(封装某些处理逻辑)

swift 复制代码
@propertyWrapper
struct Uppercase {
    private var value: String = ""
    var wrappedValue: String {
        get { value }
        set { value = newValue.uppercased() }
    }
}

然后,在需要的地方,修饰属性。(复用代码)

less 复制代码
struct User {

    @Uppercase    // 使用属性包装器 修饰
    var name: String

    ...
}

这样,每次对 name 进行set,都会"继承"自动大写的处理逻辑

其他场景:

  • 限制范围
  • 自动缓存
  • UserDefaults存储
  • 自动日志

带参数的 属性包装器

场景:如,给表示年纪的属性,限制范围。

python 复制代码
@propertyWrapper
struct RangeLimit {

    private var value: Int

    let min: Int
    let max: Int

    init(wrappedValue: Int,
         min: Int,
         max: Int) {

        self.min = min
        self.max = max

        self.value = Swift.max(min,
                               Swift.min(max, wrappedValue))
    }

    var wrappedValue: Int {
        get { value }
        set {
            value = Swift.max(min,
                              Swift.min(max, newValue))
        }
    }
}

使用

less 复制代码
struct User {

    @RangeLimit(min: 0, max: 100)
    var age: Int = 50
}

这样,即使给 user.age = 150 ,其值会限制在 100以内。

Property Wrapper + 泛型

任何类型,都可修饰

swift 复制代码
@propertyWrapper
struct Cache<T> {

    private var value: T

    init(wrappedValue: T) {
        self.value = wrappedValue
    }

    var wrappedValue: T {
        get { value }
        set {
            // ....
            value = newValue 
        }
    }
}

常见使用场景

1、封装UserDefault

vbnet 复制代码
@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 UserDefaultConfig {

    @UserDefault(key: "token", defaultValue: "")
    static var token: String
    
    ...
}

使用

ini 复制代码
UserDefaultConfig.token = "abc"
相关推荐
黄敬峰10 小时前
从 DFS 遍历到抖音推荐算法:前端工程师的硬核复习笔记
前端
zach10 小时前
网页中的虚拟滚动技术是不是源自IOS中的tableview的机制
前端
林希_Rachel_傻希希10 小时前
1小时速通React之Hooks
前端·javascript·面试
柯克七七10 小时前
公司前端项目打包体积从 2MB 降到 400KB,我改了这四个配置
前端
英勇无比的消炎药10 小时前
我才发现这些架构的“拆”与“合”哲学
前端
shen_10 小时前
AI Coding:前端UI规范笔记
前端
llz_11210 小时前
web-第五次课后作业
前端·后端·http
恋猫de小郭11 小时前
Redis 作者反驳「中国模型之所以强,是因为通过 API 蒸馏了美国模型」
前端·人工智能·ai编程
Darling噜啦啦11 小时前
Canvas 游戏开发与数据可视化实战:从飞机大战到 ECharts 报表
前端·echarts·canvas