网站底部的制作,做企业网站有什么好处,深圳律师网站建设,wordpress如何做主页设置文章目录 OC对象 - 关联对象#xff08;如何给分类添加成员变量#xff09;1. 基本使用1.1 提供的API1.1.1 添加关联对象1.1.2 获得关联对象1.1.3 移除所有关联对象1.1.3 修饰符 1.2 使用方法1.2 Key的常见用法1.2.1 使用的get方法的selecor作为key1.2.2 使用指针的地址作为k… 文章目录 OC对象 - 关联对象如何给分类添加成员变量1. 基本使用1.1 提供的API1.1.1 添加关联对象1.1.2 获得关联对象1.1.3 移除所有关联对象1.1.3 修饰符 1.2 使用方法1.2 Key的常见用法1.2.1 使用的get方法的selecor作为key1.2.2 使用指针的地址作为key1.2.3 使用static字符作为key1.2.4 使用属性名作为key 1.3 错误用法举例 2. 实现原理2.1 核心对象2.2 核心对象之间的关联2.2.1 示意图 扩展如果setValue传了nil源码 没有 weak OC对象 - 关联对象如何给分类添加成员变量
Category分类的底层结构中没有成员变量ivar因此不能给分类添加成员变量在分类里面声明的属性只会生成 get/set 方法的声明没有方法的实现
所以我们不能直接给分类添加成员变量但是可以间接实现那就是使用关联对象
1. 基本使用
1.1 提供的API
1.1.1 添加关联对象
void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy)1.1.2 获得关联对象
id objc_getAssociatedObject(id object, const void * key)1.1.3 移除所有关联对象
void objc_removeAssociatedObjects(id object)1.1.3 修饰符
objc_AssociationPolicy对应的修饰符OBJC_ASSOCIATION_ASSIGNassignOBJC_ASSOCIATION_RETAIN_NONATOMICstrong, nonatomicOBJC_ASSOCIATION_COPY_NONATOMICcopy, nonatomicOBJC_ASSOCIATION_RETAINstrong, atomicOBJC_ASSOCIATION_COPYcopy, atomic
1.2 使用方法
创建ZSXPerson类以及它的分类ZSXPersonTextZSXPersonText.h中声明想要添加的属性ZSXPersonText.m中使用关联对象API实现 get/set 方法
ZSXPerson类
interface ZSXPerson : NSObjectendimplementation ZSXPersonendZSXPersonTest.h
interface ZSXPerson (Test)property (nonatomic, copy) NSString *name;
property (nonatomic, assign) int weight;endZSXPersonTest.m
#import ZSXPersonTest.h
#import objc/runtime.himplementation ZSXPerson (Test)- (void)setName:(NSString *)name {objc_setAssociatedObject(self, selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}- (NSString *)name {// 隐式参数: _cmd相当于当前方法的selecor。还有 self 也是隐式参数return objc_getAssociatedObject(self, _cmd);
}- (void)setWeight:(int)weight {objc_setAssociatedObject(self, selector(weight), (weight), OBJC_ASSOCIATION_ASSIGN);
}- (int)weight {return [objc_getAssociatedObject(self, _cmd) intValue];
}end初始化两个实例对象给属性设置不同的值然后打印属性值 可以看到我们像正常使用对象的属性一样使用分类中创建的属性
1.2 Key的常见用法
我们上面的示例使用的get方法的selecor来作为Key这种写法相对比较简洁
1.2.1 使用的get方法的selecor作为key
objc_setAssociatedObject(obj, selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)objc_getAssociatedObject(obj, selector(getter))
1.2.2 使用指针的地址作为key
static void *MyKey MyKey;
objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)objc_getAssociatedObject(obj, MyKey)
1.2.3 使用static字符作为key
static char MyKey;
objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)objc_getAssociatedObject(obj, MyKey)
1.2.4 使用属性名作为key
objc_setAssociatedObject(obj, “property”, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);objc_getAssociatedObject(obj, “property”);
1.3 错误用法举例
static void *MyKey;
objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)objc_getAssociatedObject(obj, MyKey)
如上写法没有给*MyKey他相当于是NULL这时候如果再有另一个属性使用Keystatic void *OtherKey;*MyKey和*OtherKey都是 NULL这就相当于把多个属性都与NULLKey关联明显就出问题了
2. 实现原理
学习OC对象本质时我们知道对象实际被转化成struct ClassName_IMPL结构体对象的成员变量的值保存在该结构体中例如
struct ZSXStuden_IMPL {struct NSObject_IMPL NSObject_IVARS;int weight
};使用关联对象给分类添加的成员变量他并不是保存在该结构体下因为Category分类的底层结构中并没有ivar。
他是存储在全局的统一的一个AssociationsManager中
2.1 核心对象
AssociationsManagerAssociationsHashMapObjectAssociationMapObjcAssociation
2.2 核心对象之间的关联
关联对象是通过这四个核心对象共同完成的他们之间的关系是这样的
AssociationsManager 里面是一个AssociationsHashMap 类型的成员 mapAssociationsHashMap看名字是一个HashMap我们可以认为是 iOS 中的字典这个字段的 key 是被添加关联对象的对象的地址value 是个ObjectAssociationMapObjectAssociationMap一样认为是个字典key 是我们调用objc_setAssociatedObject时传入的 keyvalue 是ObjectAssociationObjectAssociation里面有两个成员_policy是我们设置的修饰符比如OBJC_ASSOCIATION_ASSIGN_value是我们传入的值value
2.2.1 示意图 扩展
如果setValue传了nil
如果这么操作person.name nil相当于person的name这个关联对象就是擦除如下图的数据 源码 没有 weak
objc_AssociationPolicy的值并没有weak这点我们在使用的时候需要注意 oubijiexi