关联对象存放自定义数据
关于objc_setAssociatedObject和objc_getAssociatedObject
最近是在52个提高IOS高质量代码中看到这个特性的.
在我写代码的过程中,我感觉这种方式可以提供代理中的高聚合(和RAC的函数式编程有异曲同工之妙)
先把代码上上来:
- (void)viewDidLoad {
[super viewDidLoad];
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"信息" message:@"提示" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确认", nil];
void (^block)(NSInteger) = ^(NSInteger buttonIndex){
if (buttonIndex == 0) {
NSLog(@"取消按钮");
}else if (buttonIndex == 1){
NSLog(@"确认按钮");
}
};
objc_setAssociatedObject(alert, ALERTVIEWKEY, block, OBJC_ASSOCIATION_COPY);
//
// NSString* str = @"存储自定义数据";
//
// objc_setAssociatedObject(alert, ALERTVIEWKEY, str, OBJC_ASSOCIATION_COPY);
[alert show];
}
在实现代理中,代码如下:
#pragma alertDelegate
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex: (NSInteger)buttonIndex{
void(^block)(NSInteger) = objc_getAssociatedObject(alertView, ALERTVIEWKEY);
block(buttonIndex);
// NSString* str = objc_getAssociatedObject(alertView, ALERTVIEWKEY);
// NSLog(@"%@",str);
NSLog(@"%ld",(long)buttonIndex);
}
我们所得到的效果是可以在上面viewDidload代码中直接执行了按钮的响应.
点击不同的按钮作出相应的动作.
实际上,在set方法中:
objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)
方法中,我们可以在id value传入任意参数,字符串(如注释代码中str的传递),数组,字典等,当然,例子中传递匿名函数就是较为灵活的用法.
第一个参数 <#id object#>传入对象
第二个参数 <#const void *key#>为一个key,一般格式为
static void * �NAME = "NAME";第三个参数 需要传递的对象,如匿名函数,字符串,数组等对象.(一般考虑传递信息,自定义数据,灵活的非常大)
-
第四个参数 定义的是objc_AssociationPolicy枚举,根据第三个参数来决定这个参数的@property到底是assign,还是nonatomic,retain,还是nonatomic,copy,还是retain,或者的单纯的copy.
OBJC_ASSOCIATION_ASSIGN = 0, /**< Specifies a weak reference to the associated object. */ OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. * The association is not made atomically. */ OBJC_ASSOCIATION_COPY_NONATOMIC = 3, /**< Specifies that the associated object is copied. * The association is not made atomically. */ OBJC_ASSOCIATION_RETAIN = 01401, /**< Specifies a strong reference to the associated object. * The association is made atomically. */ OBJC_ASSOCIATION_COPY = 01403 /**< Specifies that the associated object is copied. * The association is made atomically. */
而代理中调用runtime的get方法:
objc_getAssociatedObject(<#id object#>, <#const void *key#>
- <#id object#>放入对象(代理或者通过其他方式(如属性,指针)放入存储了自定义数据的对象
- <#const void *key#>为记录了当初存储该自定义数据的键值
注意
其实这种方法并不推荐大家经常使用,因为滥用的话容易导致代码失控,难于调试.
- 可以通过"关联对象"机制把两个对象连接起来
- 定义关联对象时可以指定内存管理语义,用以模仿定义属性时采用的"拥有关系"和"非拥有关系"
- 只有在其他做法不可行才应选择关联对象,因为这种做法通常会引入难于查找的bug