最近在看runtime的相关知识,感觉里面东西还蛮多的,反正感觉runtime被戴上了很多高大上的帽子。查看了很多文章,下面两个头文件是被提及的最多的,上面一个头文件主要提及到OC中的类、方法、属性和成员变量,详细的说明了他们的本质,而下面的头文件说明了OC中方法调用的本质,同时这些头文件中涉及到很多C语言中的概念,主要是结构体,结构体指针等,看着有点晕乎。
#import <objc/runtime.h>
#import <objc/message.h>
但是我写这篇文章的主要意图是为了给runtime的关联对象做一个总结,当然现在也只是初步了解,后期有新的看法就会更新这篇文章的。
1.关联对象的概念
关联对象说的简单点就是利用键值对的方式把两个对象关联起来,而关联的唯一标示就是key值
2.关联对象常用的方法
/**
* @author liyong
*
* 为object添加关联对象value
*
* @param object 关联对象中的被关联的对象
* @param key 关联的key值(这个key值必须保证是一个对象级别的唯一常量😂这地方有待研究,一个key值不知道为啥这么复杂)
* @param value 关联的对象
* @param policy 关联的内存管理策略
*
* @return
*/
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
关联的key值有三种推荐值
1.声明 static char kAssociatedObjectKey; ,使用 &kAssociatedObjectKey 作为 key 值
2.声明 static void *kAssociatedObjectKey = &kAssociatedObjectKey; ,使用 kAssociatedObjectKey 作为 key 值
3.用 selector ,使用 getter 方法的名称作为 key 值(这种方法用的比较多)policy是关联的对象的内存管理策略,是一个枚举类型,值有如下五种,使用方法跟属性的描述一样
OBJC_ASSOCIATION_ASSIGN // 对关联对象进行弱引用
OBJC_ASSOCIATION_RETAIN_NONATOMIC // 对关联对象进行强引用(非原子)
OBJC_ASSOCIATION_COPY_NONATOMIC // 对关联对象进行拷贝引用(非原子)
OBJC_ASSOCIATION_RETAIN // 对关联对象进行强引用
OBJC_ASSOCIATION_COPY // 对关联对象进行拷贝引用
/**
* @author liyong
*
* 根据被关联的对象和关联的key值获取关联的对象
*
* @param object 关联对象中的被关联的对象
* @param key 关联的key值
*
* @return 关联的对象
*/
objc_getAssociatedObject(id object, const void *key)
/**
* @author liyong
*
* 移除被关联对象的所有关联对象
* 但是这个方法用的不多,把objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
* 中的value设为nil就会根据key清空object关联的对象
*/
objc_removeAssociatedObjects(id object)
大家要是觉得注释的不是很好的话,<objc/runtime.h>
中有详细的英文注释。
3.关联对象的用法
关联对象用的最多的就是为已有的类添加属性(关于属性和实例变量的区别可以查看属性与实例变量),至于别的用法我暂时还没遇到😂😂(我感觉runtime在开发中用的本来就少,但是对runtime的学习有助于对OC和iOS开发的深入了解)。
话不多说,直接上代码
@interface LYPersonModel (testCategory)
@property (copy, nonatomic) NSString *englishName;
@end
@implementation LYPersonModel (testCategory)
- (void)setEnglishName:(NSString *)englishName
{
objc_setAssociatedObject(self, @selector(englishName), englishName, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)englishName
{
return objc_getAssociatedObject(self, @selector(englishName));
}
@end
代码不多,就两句,利用class_copyPropertyList()获取对象的成员变量就会发现类别中的属性也会出现列表中(但是利用class_copyIvarList()获取成员变量列表的时候发现没有待下划线的成员变量,看来关联对象只是变相的为类扩展了属性,实际上并没有扩张成员变量)。