那个网站做网编好,昨晚兰州发生了什么事,苏州建设工程质量监督网站,100个经典商业案例分析Swift | 属性包装器
1. 什么是 Swift Property Wrapper#xff1f;
Swift Property Wrapper 是一种特性#xff0c;它允许我们在声明属性时添加自定义的包装逻辑。通过使用属性包装器#xff0c;我们可以在不修改类或结构体定义的情况下#xff0c;定制属性的访问和存储方…Swift | 属性包装器
1. 什么是 Swift Property Wrapper
Swift Property Wrapper 是一种特性它允许我们在声明属性时添加自定义的包装逻辑。通过使用属性包装器我们可以在不修改类或结构体定义的情况下定制属性的访问和存储方式。这种特性在很多场景下非常有用例如属性验证、类型转换、延迟初始化等。
2. 属性包装器的定义与使用
要定义一个属性包装器我们需要创建一个实现了特定协议的结构体或类。Swift 提供了 propertyWrapper 属性包装器特性来帮助我们定义包装器。下面是一个完整的示例
propertyWrapper
struct MyWrapper {var wrappedValue: Int {willSet {// 自定义包装逻辑print(Value changing to: \(wrappedValue))}didSet {// 自定义包装逻辑print(Value changed to: \(wrappedValue))}}init(wrappedValue: Int) {self.wrappedValue wrappedValue}var projectedValue: Self {return self}
}struct MyStruct {MyWrapper(wrappedValue: 10)public var myProperty: Int
}var instance MyStruct()
instance.myProperty 20 // 输出Value changed to: 20
instance.$myProperty // 等于projectedValue编程接口
willSet设置新值之前调用。didSet新值设置完成调用。projectedValue可以使用instance.$myProperty拿到projectedValue值方便我们添加前缀、后缀、验证器验证结果等。
3. 演示
3.1. 范围限制
propertyWrapper
struct RangeLimited {var wrappedValue: Int {didSet {if wrappedValue lowerBound {wrappedValue lowerBound} else if wrappedValue upperBound {wrappedValue upperBound}}}let lowerBound: Intlet upperBound: Intinit(wrappedValue: Int, range: ClosedRangeInt) {self.lowerBound range.lowerBoundself.upperBound range.upperBoundself.wrappedValue wrappedValue}var projectedValue: Self {return self}
}struct MyStruct {RangeLimited(range: 0...100) var myProperty: Int 0
}var instance MyStruct()
instance.myProperty 150
print(myProperty value: \(instance.myProperty) lowerBound: \(instance.$myProperty.lowerBound) upperBound: \(instance.$myProperty.upperBound)) // 输出: myProperty value: 100 lowerBound: 0 upperBound: 1003.2. 用户名验证器
propertyWrapper
struct MyUsernameValidator {var wrappedValue: String {didSet {self.isValided wrappedValue.count self.minLength wrappedValue.count self.maxLength}}var isValided: Bool falsevar minLength: Intvar maxLength: Intinit(wrappedValue: String, minLength: Int, maxLength: Int) {self.wrappedValue wrappedValueself.minLength minLengthself.maxLength maxLength}var projectedValue: Self { self }
}struct MyStruct {MyUsernameValidator(wrappedValue: , minLength: 3, maxLength: 10) public var myUsername: String
}var instance MyStruct()
print(myUsername: \(instance.myUsername) isValided: \(instance.$myUsername.isValided)) // myUsername: isValided: false
instance.myUsername yimt
print(myUsername: \(instance.myUsername) isValided: \(instance.$myUsername.isValided)) // myUsername: yimt isValided: true4. 注意事项
在使用属性包装器时需要注意以下几点
属性包装器只能用于类或结构体的属性不能用于全局变量或局部变量。尽量保持属性包装器的逻辑简洁明了不要在包装器中实现复杂的业务逻辑。谨慎使用属性包装器过度使用可能会增加代码复杂性和难以维护。