美文网首页
runtime 之关联对象

runtime 之关联对象

作者: 沉默着欢喜丶 | 来源:发表于2018-04-06 18:08 被阅读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>

    相关文章

      网友评论

          本文标题:runtime 之关联对象

          本文链接:https://www.haomeiwen.com/subject/tdeshftx.html