《Effective Objective-C 2.0》- 10:

2018-08-16  本文已影响0人  WhistleCai

我们有时需要在对象中存放相关信息。这时我们通常会从对象所属的类中继承一个子类,然后改用这个子类对象。然而并非所有情况下都能这么做,有时类的实例可能是由某种机制所创建的,而开发者无法令这种机制创建出自己所写的子类实例。此时就可以使用“关联对象”的方式来解决。

(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...");
}];

要点:

  1. 可以通过“关联对象”机制来把两个对象连起来。
  2. 只有在其他做法不可行时才应选用关联对象,因为这种做法通常会引入难于查找的bug。
上一篇 下一篇

猜你喜欢

热点阅读