Swift5.1学习随笔之扩展extension添加属性

2020-05-19  本文已影响0人  SAW_
class Person {
    var age = 0
}
extension Person {
    var name = "" // 报错:Extensions must not contain stored properties
}

默认情况下扩展不能包含存储属性,只能包含计算属性(本质是方法)。
可以通过使用关联对象是实现扩展添加属性。(swift中需要导入Foundation框架)

/*
 * object 需要关联的对象
 * key 需要传入一个地址值,将来用来取出newValue的值,外部定义一个全局变量,将全局变量的地址值传入
 * value 需要存储的值
 * policy 使用策略:
    OBJC_ASSOCIATION_ASSIGN
    OBJC_ASSOCIATION_RETAIN_NONATOMIC
    OBJC_ASSOCIATION_COPY_NONATOMIC
    OBJC_ASSOCIATION_RETAIN
    OBJC_ASSOCIATION_COPY
 */
public func objc_setAssociatedObject(_ object: Any, _ key: UnsafeRawPointer, _ value: Any?, _ policy: objc_AssociationPolicy)
/*
 * object 需要关联的对象
 * key 通过外部定义的全局变量的地址值来确定取出存储的值
 */
public func objc_getAssociatedObject(_ object: Any, _ key: UnsafeRawPointer) -> Any?

最终实现:

var age_key = 0
extension Person {
    var age: Int {
        get {
            objc_getAssociatedObject(self, &age_key) as! Int
        }
        set {
            objc_setAssociatedObject(self, &age_key, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
}

var p = Person()
p.age = 10
print(p.age) // 10

但是由于这个key只是需要在内部使用,在外部定义全局变量不太合理,因此需要优化,将key写在扩展内部:

extension Person {
    //用任何类型都行,主要是那地址来用,只需要用Bool,只需要占用2个字节
    private static var AGE_KEY = false
    var age: Int {
        get {
            objc_getAssociatedObject(self, &Self.AGE_KEY) as! Int
        }
        set {
            objc_setAssociatedObject(self, &Self.AGE_KEY, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读