我们有时需要在对象中存放相关信息。这时我们通常会从对象所属的类中继承一个子类,然后改用这个子类对象。然而并非所有情况下都能这么做,有时类的实例可能是由某种机制所创建的,而开发者无法令这种机制创建出自己所写的子类实例。此时就可以使用“关联对象”的方式来解决。
(1)定义:某个对象通过一个唯一的key连接到一个类的实例
(2)原理:runtime提供的方法
/** 参数含义:
id object:被关联的对象(如xiaoming)
const void *key:关联的key,要求唯一
id value:关联的对象(如dog)
objc_AssociationPolicy policy:内存管理的策略
*/
// 1>将object和value关联在一起:
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
// 2>根据key值获取关联对象
id objc_getAssociatedObject(id object, const void *key);
// 3>移除所有关联对象
void objc_removeAssociatedObjects(id object);
应用举例,使用block去实现button的点击回调:
// .h
// 1>声明一个button点击事件的回调block
typedef void(^ButtonClickCallBack)(UIButton *button);
// 2>为UIButton增加的回调方法
- (void)handleClickCallBack:(ButtonClickCallBack)callBack;
// .m
// 实现回调方法
- (void)handleClickCallBack:(ButtonClickCallBack)callBack {
objc_setAssociatedObject(self, &buttonClickKey, callBack, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self addTarget:self action:@selector(buttonClicked) forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonClicked {
ButtonClickCallBack callBack = objc_getAssociatedObject(self, &buttonClickKey);
if (callBack) {
callBack(self);
}
}
// 具体调用:
[self.testButton handleClickCallBack:^(UIButton *button) {
NSLog(@"click...");
}];
要点:
- 可以通过“关联对象”机制来把两个对象连起来。
- 只有在其他做法不可行时才应选用关联对象,因为这种做法通常会引入难于查找的bug。
网友评论