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)
}
}
}
网友评论