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

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)
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。