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

关联对象存放自定义数据

作者: 蔡俊宇 | 来源:发表于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