Objective-C 中的对象关联(Associated Objects)
by
###目录
- 什么是对象关联(Associated Objects)
- 如何使用
- 注意事项
- 参考资料
什么是对象关联(Associated Objects)
对象关联是Objective-C 2.0运行时的一个特性,起始于OS X Snow Leopard和iOS 4。我们有时候需要在对象中存放一些相关的信息,而又无法通过别的手段实现时,就可以把这些信息通过对象关联的方法与对象关联起来,在需要的时候通过对应的 key 就可以获取到对象的这些信息,比如说我们可以在 Category 中通过对象关联添加自定义的属性。对象关联通过 <objc/runtime.h> 中定义的三个方法实现的:
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
id objc_getAssociatedObject(id object, const void *key);
objc_removeAssociatedObjects(id object);
如何使用对象关联
我们可以使用关联对象在 Category 中添加自定义的属性,比如为一个 GHPerson 类添加一个体重的属性(weight):
GHPerson+GHAssociatedObject.h
#import "GHPerson.h"
@interface GHPerson (GHAssociatedObject)
@property (nonatomic, strong) NSNumber *weight;
@end
GHPerson+GHAssociatedObject.m
#import "GHPerson+GHAssociatedObject.h"
#import <objc/runtime.h>
static char weightKey;
@implementation GHPerson (GHAssociatedObject)
@dynamic weight;
- (void)setWeight:(NSNumber *)weight
{
objc_setAssociatedObject (self,&weightKey,weight,OBJC_ASSOCIATION_RETAIN);
}
- (NSNumber *)weight
{
return (NSNumber *)objc_getAssociatedObject(self, &weightKey);
}
@end
其中 weightKey 是我们关联对象时用到的key,一般最好使用一个 char 类型的静态全局变量。从关联这个角度上看,我们用的属性不过是把对象关联到了一个实例变量上面。
我们看到 objc_setAssociatedObject 中的第 4 个参数,它表明了一个引用的关系,和 @property 中的属性等同:
OBJC_ASSOCIATION_ASSIGN 等同于 @property (assign) 或 @property (unsafe_unretained)
OBJC_ASSOCIATION_RETAIN_NONATOMIC 等同于 @property (nonatomic, strong),其不可以被原子化
OBJC_ASSOCIATION_COPY_NONATOMIC 等同于 @property (nonatomic, copy),其不可以被原子化
OBJC_ASSOCIATION_RETAIN 等同于 @property (atomic, strong), 可以被原子化
OBJC_ASSOCIATION_COPY 等同于 @property (atomic, copy), 可以被原子化
注意事项
- 不应该用 objc_removeAssociatedObjects() 来删除对象的属性,因为可能会导致其他客户对其添加的属性也被移除了。规范的方法是:调用 objc_setAssociatedObject 方法并传入一个 nil 值来清除一个关联。
- 应该小心使用对象关联,不要滥用,因为可能会引起难以调试的bug。
参考资料
Subscribe via RSS