objc_setAssociatedObject 使用

  • UIAlertView的扩展

.h文件

#import 
typedef void (^successBlock)(NSInteger buttonIndex);

@interface UIAlertView (Block)<UIAlertViewDelegate>

- (void)showWithBlock:(successBlock)block;

@end

.m文件

#import "UIAlertView+Block.h"
#import 

static const char alertKey;

@implementation UIAlertView (Block)

- (void)showWithBlock:(successBlock)block
{
    if (block)
    {
        objc_setAssociatedObject(self, &alertKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
        self.delegate = self;
    }

    [self show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    successBlock block = objc_getAssociatedObject(self, &alertKey);

    block(buttonIndex);
}

@end
  • UIButton的扩展

.h文件

#import 

typedef void (^btnBlock)();

@interface UIButton (Block)

- (void)handelWithBlock:(btnBlock)block;

@end

.m文件

#import "UIButton+Block.h"
#import 

static const char btnKey;

@implementation UIButton (Block)

- (void)handelWithBlock:(btnBlock)block
{
    if (block)
    {
        objc_setAssociatedObject(self, &btnKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }

    [self addTarget:self action:@selector(btnAction) forControlEvents:UIControlEventTouchUpInside];
}

- (void)btnAction
{
    btnBlock block = objc_getAssociatedObject(self, &btnKey);
    block();
}

@end

tips: 使用objc_setAssociatedObject,需要引入头文件 #import 
void objc_setAssociatedObject(id object, const void key, id value, objc_AssociationPolicy policy);id objc_getAssociatedObject(id object, const voidkey);

这两个方法可以让一个对象和另一个对象关联,就是说一个对象可以保持对另一个对象的引用,并获取那个对象。有了这些,就能实现属性功能了。 policy可以设置为以下这些值:

enum {OBJC_ASSOCIATION_ASSIGN = 0,
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
OBJC_ASSOCIATION_RETAIN = 01
OBJC_ASSOCIATION_COPY = 01403
};

假定我们想要动态地将一个Tap手势操作连接到任何UIView中,并且根据需要指定点击后的实际操作。这时候我们就可以将一个手势对象及操作的block对象关联到我们的UIView对象中。这项任务分两部分。首先,如果需要,我们要创建一个手势识别对象并将它及block做为关联对象。如下代码所示:

这段代码检测了手势识别的关联对象。如果没有,则创建并建立关联关系。同时,将传入的块对象连接到指定的key上。注意block对象的关联内存管理策略。

手势识别对象需要一个target和action,所以接下来我们定义处理方法:

我们需要检测手势识别对象的状态,因为我们只需要在点击手势被识别出来时才执行操作。

从上面的例子我们可以看到,关联对象使用起来并不复杂。它让我们可以动态地增强类现有的功能。我们可以在实际编码中灵活地运用这一特性


- (void)viewDidLoad {    

[super viewDidLoad];      

//    static const char associatedButtonkey;

                UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];

    [btn setTitle:@"点我" forState:UIControlStateNormal];    [self.view addSubview:btn];    [btn setFrame:CGRectMake(50505050)];    btn.backgroundColor = [UIColor redColor];        [btn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];        // Do any additional setup after loading the view, typically from a nib.    }

-(void)click:(UIButton *)sender{    NSString *message = @"你是谁";       

 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"我要传值·" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];    alert.delegate = self;    [alert show];    

    //#import 头文件    //objc_setAssociatedObject需要四个参数:源对象,关键字,关联的对象和一个关联策略。        //1 源对象alert   

 //2 关键字 唯一静态变量key associated key  

  //3 关联的对象 sender   

 //4 关键策略  OBJC_ASSOCIATION_ASSIGN

//    enum {//        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. *///    };    

objc_setAssociatedObject(alert, @"msgstr", message,OBJC_ASSOCIATION_ASSIGN);    

//把alert和message字符串关联起来,作为alertview的一部分,关键词就是msgstr,之后可以使用objc_getAssociatedObject从alertview中获取到所关联的对象,便可以访问message或者bin了    

//    即实现了关联传值    

objc_setAssociatedObject(alert, @"btn property",sender,OBJC_ASSOCIATION_ASSIGN);

}

-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{            

//通过 objc_getAssociatedObject获取关联对象   

 NSString  *messageString =objc_getAssociatedObject(alertView, @"msgstr");        

    UIButton *sender = objc_getAssociatedObject(alertView, @"btn property");   

 NSLog(@"%ld",buttonIndex);   

 NSLog(@"%@",messageString); 

   NSLog(@"%@",[[sender titleLabel] text]

);           

 //使用函数objc_removeAssociatedObjects可以断开所有关联。通常情况下不建议使用这个函数,因为他会断开所有关联。只有在需要把对象恢复到“原始状态”的时候才会使用这个函数。

}

终端打印:

2015-07-22 16:18:35.294 test[5174:1441210

2015-07-22 16:18:35.295 test[5174:144121] 你是谁

2015-07-22 16:18:35.295 test[5174:144121] 点我

你可能感兴趣的:(iOS)