如果想用一个系统的类,但是该类又不满足需求,首先肯定是继承自系统的类,重新构建一个类,但这种方法,如果我们需求的类之比原来的类多一个属性呢,继承似乎又显得比较麻烦,这种情况,使用类目就非常的方便了,但是类目又不能添加属性,怎么办呢,这个时候也许用runtime的关联对象就可以办到了。
要想在runtime中完成动态添加属性,需要导入#import<objc/runtime.h>
这个头文件,当然最新的Xcode也支持如此导入@import ObjectiveC;
。需要了解下面两个方法:
/**
* 设置关联对象
*
* @param object 需要添加关联的对象
* @param key 添加的唯一标识符
* @param value 关联的对象
* @param policy 关联的策略,是个枚举
*/
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
那个枚举策略如下:
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy){
OBJC_ASSOCIATION_ASSIGN = 0, //assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //retain,nonatomic(非原子性)
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //copy,nonatomic(非原子性)
OBJC_ASSOCIATION_RETAIN = 01401, //retain(原子性)
OBJC_ASSOCIATION_COPY = 01403, //copy(原子性)
};
这个也就不多说了,熟悉内存管理的人应该也不会陌生。
/**
* 获得关联对象
*
* @param object 添加过关联的对象
* @param key 添加的唯一标识符
*/
objc_getAssociatedObject(id object, const void *key)
按照个人习惯,举个例子,首先创建一个YObject的类
class YObject: NSObject {
//定义两个属性
/// 姓名
var name : String?
/// 电话
var tele : String?
}
这个时候有一个需求,需要在上面的类中添加一个parentName
的属性,继承可以完成需求,但是只为了添加一个属性而重新创建一个新类,着实心累,这个时候用关联对象就方便多了,在延展中实现如下方法:
var ConstParentName:String = "ConstParentName"
extension YObject
{
//添加属性
/// 监护人的姓名
var parentName :String?
{
set{//Setter方法
objc_setAssociatedObject(self, &ConstParentName, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
}
get{//Getter方法
return objc_getAssociatedObject(self, &ConstParentName) as? String
}
}
}
在main方法里验证测试一下
let object : YObject = YObject()
object.name = "Yue"
object.tele = "11011011011"
object.parentName = "parent"
print("name =\(object.name) tele =\(object.tele) parentName = \(object.parentName) ")
打印结果如下:
name =Optional("Yue") tele =Optional("11011011011") parentName = Optional("parent")
结果显示,我们确实为他添加了一个parentName的属性Thanks()