定义:
在 Swift 5.1 中引入了@propertyWrapper这个特性,属性包装器是在 管理属性存储方式的代码和定义属性的代码之间添加了一层分离。管理属性的set、get方式由属性包装器接管,定义属性的代码还在原来的类中。**
参考来源 →
作用:
如果你有属性提供了线程安全检查或将数据存到数据库功能,那么你将需要为每个属性编写类似代码。有了属性包装器,我们就可以避免类似重复代码。
使用场景:
▪验证属性值的合法性,例如范围、格式、唯一性等;
▪处理属性值的变化,例如映射、转换、格式化等;
▪控制属性的存储和访问方式,例如延迟加载、懒加载、缓存等;
▪实现属性的依赖关系,例如自动更新、自动绑定等。
实现:
通过 @propertyWrapper来标识struct, enum, class实现属性包装。
要点:
▪必须使用属性@propertyWrapper进行定义;
▪必须为包装器添加 wrappedValue 属性;
▪@propertyWrapper 只能用于属性,不能用于计算属性或者函数;
▪@propertyWrapper 可以应用于单个属性或者整个结构体/类中的所有属性;
▪使用 @propertyWrapper 时,需要为包装器提供一个默认值;
▪如果属性包装器需要进行一些额外的初始化,需要使用 init(wrappedValue:) 方法。
结构示例:
@propertyWrapper
struct NumberWrapper {
private var value: Int = 0
var wrappedValue: Int {
get {
return value
}
set {
// value <= 10
value = min(newValue, 10)
}
}
}
struct Number {
// 告诉编译器使用Wrapper包装器包装该属性
@NumberWrapper var number: Int
}
调用分析:
使用@NumberWrapper时编译器会转为下面的执行过程
struct Number {
private var _number = NumberWrapper()
var number: Int {
get { return _number.wrappedValue }
set { _number.wrappedValue = newValue }
}
}
▪调用 Number 中number 的 set 函数
▪调用 属性包装器的 _number.wrappedValue 的 set函数
▪调用 number = min(newValue, 10) 来保证新设置的值小于等于 10
使用限制:
- 协议的属性不支持使用属性包装器
- extension中不可以使用(扩展内声明的非静态属性不能有包装器)
- enum中不可以使用(属性包装器只能应用于属性)
- class里的 wrapper property 属性不能被重写
- wrapper 不能定义 getter 或 setter 方法 ( 属性包装器不能应用于计算属性)
- wrapper 属性不能被 lazy、 @NSCopying、 @NSManaged、 weak、 或者 unowned 修饰









网友评论