属性包装器Property Wrappers

代码示例:

@propertyWrapper
struct Increase<T> {
    var wrappedValue : T {
        get {return value1}
        set {
            value1 = newValue
            if T.self is Int.Type {
                print("\(T.self)")
            }
            if T.self is NSObject.Type || T.self is (NSObject?).Type {
                print("\(T.self)")
            }
        }
    }
    
    var projectedValue : Increase<T> {return self}
    
    private var value1 : T
    init(wrappedValue: T) {
        self.value1 = wrappedValue
    }
    public func printValue() {
        if let v = wrappedValue as? Int {
            print("Increase: value=\(v+1)")
        }
    }
}


class SwiftTestObject : NSObject {
	@Increase var wrappedInt : Int = 1
    @Increase(wrappedValue: nil) var wrappedObject : NSObject?
	func testFunc() {
		self.wrappedObject.  //NSObject
		_wrappedObject  //Increase<NSObject>
		self.$wrappedObject.   //Increase<NSObject>
	}
}
  1. @propertyWrapper 来声明,必须带 泛型定义。
  2. 必须创建 var wrappedValue ,同时重写 set get方法。
  3. 在声明对应属性包装器 属性的class里,可以用 _value 来访问 Increase 对象。用 self.value 来访问对应的 T 类型对象
  4. 可以用 @Increase var value :int = 1. 或是 @Increase(wrappedValue: 1) var value : Int. 来声明并初始化
  5. 如果外面其他地方要访问 Increase 对象,必须在 propertyWrapper 里声明一个 projectedValue 来返回self,外面即可用 object.$value 语法糖来访问。

属性包装器的限制

  1. 带有包装器的属性不能在子类中覆盖。
  2. 具有包装器的属性不能是lazy,@NSCopying,@NSManaged,weak或unowned
  3. 具有包装器的属性不能具有自定义的set或get方法。
  4. wrappedValue,init(wrappedValue :)和projectedValue必须具有与包装类型本身相同的访问控制级别
  5. 不能在协议或扩展中声明带有包装器的属性。

参考:Swift 5 属性包装器Property Wrappers完整指南