runtime 之关联对象

2018-04-06  本文已影响0人  沉默着欢喜丶

如何给一个NSArray添加一个属性,不能使用继承。 分类不能添加属性,只能添加方法。
这时就可以使用关联对象。

关联对象

就是给某个对象关联多个对象,这些对象用一个唯一的key区分。
关联对象一般用于动态的扩展一个对象,但是这一般都是在其他方法不行的事后才会使用,因为关联对象很可能会出现难以查找的bug。

存储关联对象的时候一样有内存管理策略。

OBJC_ASSOCIATION_ASSIGN = 0,               assign
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,     nonatomic,retain 
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,       nonatomic,copy
OBJC_ASSOCIATION_RETAIN = 01401,           retain
OBJC_ASSOCIATION_COPY = 01403,            copy

他们每个都对应OC上的内存管理策略。

具体的方法有三个:

//关联对象 
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
//获取关联的对象 
id objc_getAssociatedObject(id object, const void *key) 
//移除关联的对象 
void objc_removeAssociatedObjects(id object)

具体的参数:

id object:被关联的对象
const void *key:关联的key,要求唯一
id value:关联的对象
objc_AssociationPolicy policy:内存管理的策略

具体用法:

在一个button的分类里面添加一个timeInterval属性。如果不使用关联对象,这个属性没有作用,也不具有set和get方法。
使用关联对象:

重写get和set方法实现关联。
- (NSTimeInterval)timeInterval
{
return [objc_getAssociatedObject(self, _cmd) doubleValue];
}
- (void)setTimeInterval:(NSTimeInterval)timeInterval
{
objc_setAssociatedObject(self, @selector(timeInterval), @(timeInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

这样就可以在button的分类里面添加一个属性了。

还有一种用法,使用UIAlertview的时候,创建了一个alert对象,还要实现它的代理去处理按钮点击方法。但是当有好多个alert对象创建了之后,他们都要通过同一个代理方法去处理点击事件。
为了区分不同的alert,一般的做法是给每个alert对象加上tag值,在代理方法去获取当前的alert对象。

使用关联对象具体代码:

static char *AlertKey = "alertKey";
- (void)viewDidLoad {
    [super viewDidLoad];

    alert = [[UIAlertView alloc] initWithTitle:@"alert" message:@"message" delegate:self cancelButtonTitle:@"cancel" otherButtonTitles:@"other", nil];
}

- (IBAction)click:(id)sender {

    void (^block) (NSInteger) = ^(NSInteger buttonIndex){
        if (buttonIndex == 0){
            NSLog(@"click cancel");
        }
        else{
            NSLog(@"click other");
        }
    };
    objc_setAssociatedObject(alert, AlertKey, block, OBJC_ASSOCIATION_COPY);
    [alert show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex: (NSInteger)buttonIndex
{
    void (^block)(NSInteger) = objc_getAssociatedObject(alertView, AlertKey);
     block(buttonIndex);
}

如果是用关联对象,就会更方便。在alert创建的时候设置一个关联对象block,并给他一个唯一的key值。创建一个关联对象block,关联当前对象和代理方法,把代理里面需要执行的方法通过block和alert的创建方法绑定。

最后不要忘了import

import <objc/objc-runtime.h>

上一篇下一篇

猜你喜欢

热点阅读