如何实现给分类“添加成员变量”?
- 默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中。但可以通过关联对象来间接实现
- 关联对象提供了以下API
1> 添加关联对象
void objc_setAssociatedObject(id object, const void * key,
id value, objc_AssociationPolicy policy)
2> 获得关联对象
id objc_getAssociatedObject(id object, const void * key)
3> 移除所有的关联对象
void objc_removeAssociatedObjects(id object)
key的常见用法
objc_AssociationPolicy修饰符
给分类添加属性实例
假如已经有一个 XGPerson的类,现在我们需要扩展这个类,并且添加一个 age 属性
#import "XGPerson.h" // 分类属性是不会生成 get\set 方法的,如果不重写这两个方法,就无法正常使用属性
@interface XGPerson (Test) @property (nonatomic,assign) int age; @end
#import "XGPerson+Test.h"
#import <objc/runtime.h> @implementation XGPerson (Test) - (void)setAge:(int)age{ // @selector(age) 这个参数只要传一个地址指针就可以
objc_setAssociatedObject(self, @selector(age), @(age), OBJC_ASSOCIATION_ASSIGN);
} - (int)age{ // 隐式参数
// _cmd = @selectior(age)
return [objc_getAssociatedObject(self, _cmd) intValue];
}
调用:
XGPerson* p1 = [[XGPerson alloc]init];
p1.name = @"p1";
p1.age = ; XGPerson* p2 = [[XGPerson alloc]init];
p2.name = @"p2";
p2.age = ; NSLog(@"p1Name:%@ p1Age:%i----p2Name:%@ p2Age:%i",p1.name,p1.age,p2.name,p2.age);
输出:
-- ::38.666084+ 关联对象(增加分类属性)[:] p1Name:p1 p1Age:----p2Name:p2 p2Age:
关联对象的原理
- 实现关联对象技术的核心对象有
AssociationsManager
AssociationsHashMap
ObjectAssociationMap
ObjcAssociation
- objc4源码解读:objc-references.mm
- 关联对象存储结构图
- 关联对象并不是存储在被关联对象本身内存中
- 关联对象存储在全局的统一的一个AssociationsManager中
- 设置关联对象为nil,就相当于是移除关联对象
移除对象关联引用源码:
当一个对象触发 dealloc 时会调用下面的代码:
可以看出,在调用 dealloc 方法时,不需要我们手动去删除 对象关联信息,它会自己去调用 删除对象关联信息