无论在MRC下还是ARC下均不需要,被关联的对象在生命周期内要比对象本身释放的晚很多,它们会在被 NSObject -dealloc 调用的object_dispose()方法中释放。
关联对象的实现
我们在 iOS 开发中经常需要使用分类(Category),为已经存在的类添加属性的需求,但是使用 @property 并不能在分类中正确创建实例变量和存取方法。
不过,通过 Objective-C 运行时中的关联对象,也就是 Associated Object,我们可以实现上述需求。
#import "DKObject+Category.h"
#import <objc/runtime.h>
@implementation DKObject (Category)
- (void)setName:(NSString *)name {
objc_setAssociatedObject(self, @selector(name), name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)name {
// 隐式参数
// _cmd == @selector(name)
return objc_getAssociatedObject(self, _cmd);
}
@end
我们使用了两个方法 objc_getAssociatedObject
以及 objc_setAssociatedObject
来模拟『属性』的存取方法,而使用关联对象模拟实例变量。
我们从三个 objc 运行时的方法为入口来对关联对象的实现一探究竟,其中两个方法是上一部分使用到的方法:
NSLog(@"以键值对形式添加关联对象")
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
NSLog(@"根据 key 获取关联对象")
id objc_getAssociatedObject(id object, const void *key);
NSLog(@"移除所有关联对象")
void objc_removeAssociatedObjects(id object);
在这里有必要解释两个问题:
- 为什么向方法中传入 @selector(name)?
- OBJC_ASSOCIATION_RETAIN_NONATOMIC 是干什么的?
关于第一个问题,我们需要看一下这两个方法的原型:
id objc_getAssociatedObject(id object, const void *key);
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
@selector(name) 也就是参数中的 key,其实可以使用静态指针 static void * 类型的参数来代替,不过在这里,笔者强烈推荐使用 @selector(name) 作为 key 传入。因为这种方法省略了声明参数的代码,并且能很好地保证 key 的唯一性。
OBJC_ASSOCIATION_RETAIN_NONATOMIC 又是什么呢?
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 // 指定相关的对象被复制,原子性
};
从这里的注释我们能看到很多东西,也就是说不同的 objc_AssociationPolicy 对应了不通的属性修饰符:
objc_AssociationPolicy | modifier |
---|---|
OBJC_ASSOCIATION_ASSIGN | assign |
OBJC_ASSOCIATION_RETAIN_NONATOMIC | nonatomic, strong |
OBJC_ASSOCIATION_COPY_NONATOMIC | nonatomic, copy |
OBJC_ASSOCIATION_RETAIN | atomic, strong |
OBJC_ASSOCIATION_COPY | atomic, copy |
网友评论