美文网首页
关联对象存放自定义数据

关联对象存放自定义数据

作者: 蔡俊宇 | 来源:发表于2016-09-21 13:05 被阅读21次

    关联对象存放自定义数据

    关于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

    相关文章

      网友评论

          本文标题:关联对象存放自定义数据

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