前言:
分类中虽然不能直接添加成员变量,但是我们可以通过间接实现添加成员变量
方法一:使用静态全局变量给分类添加属性
static NSString *_name;
-(void)setName:(NSString *)name
{
_name = name;
}
-(NSString *)name
{
return _name;
}
但是这样_name静态全局变量与类并没有关联,无论对象创建于销毁,只要程序在运行,_name变量就存在,并不是真正意义上的属性。
方法二:使用Runtime动态添加属性
Runtime提供了动态添加属性和获取属性的方法
1、动态添加属性
void objc_setAssociatedObject(id object, const void * key, id value, objc_AssociationPolicy policy)
参数一:id object : 给哪个对象添加属性,这里要给自己添加属性,用self。
参数二:void * == id key : 属性名,根据key获取关联对象的属性的值,在objc_getAssociatedObject中通过次key获得属性的值并返回。
参数三:id value : 关联的值,也就是set方法传入的值给属性去保存。
参数四:objc_AssociationPolicy policy : 策略,属性以什么形式保存。
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, // 指定一个弱引用相关联的对象
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 指定相关对象的强引用,非原子性
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, // 指定相关的对象被复制,非原子性
OBJC_ASSOCIATION_RETAIN = 01401, // 指定相关对象的强引用,原子性
OBJC_ASSOCIATION_COPY = 01403 // 指定相关的对象被复制,原子性
};
2、获得属性
objc_getAssociatedObject(id object, const void *key);
参数一:id object : 获取哪个对象里面的关联的属性。
参数二:void * == id key : 什么属性,与objc_setAssociatedObject中的key相对应,即通过key值取出value。
3、移除所有关联对象
- (void)removeAssociatedObjects
{
// 移除所有关联对象
objc_removeAssociatedObjects(self);
}
person2.degree = nil;
关联对象并不是存储在被关联对象本身内存中,而是存储在全局的统一的一个AssociationsManager中,如果设置关联对象为nil,就相当于是移除关联对象。
关联对象的实际运用中的key
static : 代表只能在此文件内访问
1、赋值的key :static void *MyKey = &MyKey;
static void *MyKey = &MyKey;
// 关联对象
objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
// 获得关联对象
objc_getAssociatedObject(obj, MyKey)
2、内存地址的key : static char MyKey;
static char MyKey;
objc_setAssociatedObject(obj, &MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, &MyKey)
const void * _Nonnull key: 仅仅是一个指针,&MyKey地址就可以, static char MyKey;不是一定要用char,这里只是它的字节是一个字节,在此仅仅只传一个指针而已
3、使用属性名作为key : #define JKRevelKey @"revel";
NSArray *str = @"revel";: 其实@"revel"就是自身的内存地址:唯一性,可以打印 str,内存地址是一样的
objc_setAssociatedObject(obj, @"property", value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_getAssociatedObject(obj, @"property");
4、使用get方法的@selecor作为key
可以使用@selector(getter)来代替_cmd
objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, @selector(getter))
网友评论