Object - C运行时应用(2)—— 使用对象关联为分类增加属性(每个对象的属性互不干扰)

Object - C运行时应用(二)—— 使用对象关联为分类增加属性(每个对象的属性互不干扰)
一、对象的关联方法有
1、 void objc_setAssociatedObject(id object, const void *key, id value,objc_AssociationPolicy policy) ,关联对象(将值value与对象object关联起来)
参数key:将来可以通过key取出这个存储的值
参数policy:存储策略(assign、copy、retain)
2、 id objc_getAssociatedObject(id object, const void *key) ,利用参数key将对象中存储的对应值取出

二、利用分类为每个对象添加属性(可作为对象的标签或存储信息)
声明代码:
@interface NSObject (CX)
/**
 *  为每一个对象添加一个name属性
 */
@property (nonatomic,copy) NSString *name;
/**
 *  为每个对象添加一个数组属性
 */
@property (nonatomic,strong) NSArray *books;
@end
实现代码:
// 用一个字节来存储key值,设置为静态私有变量,避免外界修改
static char nameKey;
- (void)setName:(NSString *)name
{
    // 将某个值与某个对象关联起来,将某个值存储到某个对象中
    objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)name
{
     return objc_getAssociatedObject(self, &nameKey);
}

static char booksKey;
- (void)setBooks:(NSArray *)books
{
    objc_setAssociatedObject(self, &booksKey, books, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSArray *)books
{
    return objc_getAssociatedObject(self, &booksKey);
}

测试:
NSString *str = @"xx";
    str.name = @"oo";
    str.books = @[@"xxoo",@"ooxx"];
    
    NSLog(@"%@,%@",str.name,str.books);

打印如下:

Object - C运行时应用(2)—— 使用对象关联为分类增加属性(每个对象的属性互不干扰)

这样连字符串页具备了一个数组属性。

三、对象关联的另一种作用:在既有类中使用关联对象存放自定义数据
     在ios开发时经常会用到UIAlertView类,该类提供了一种视图向用户展示警告信息。该类通过代理协议来处理用户的点击事件,但由于使用了代理就必须把创建警告的视图和处理按钮动作的代码分开,比如说
- (void)showAlertView
{
    UIAlertView *alert =  [[UIAlertView alloc] initWithTitle:@"UIAlertView" message:@"what do you do" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"sure", nil];
    [alert show];
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (0 == buttonIndex) {
        NSLog(@"%@",@"cancel");
    }
    else if (1 == buttonIndex)
    {
        NSLog(@"%@",@"sure");
    }
}


如果想在同一个类里处理多个警告信息视图,我们必须在代理方法中比较点击按钮的索引,并借此编写相应的逻辑,如果能够在创建警告视图的时候直接把处理逻辑的代码写好那将会很便于阅读,这时可以考虑用关联对象,设定一个与alert对象关联的代码块,等到执行代理方法时再将其读取出来

- (void)viewDidLoad {
    [super viewDidLoad];
    [self showAlertView];
}
static char myAlerViewKey;
- (void)showAlertView
{
    UIAlertView *alert =  [[UIAlertView alloc] initWithTitle:@"UIAlertView" message:@"what do you do" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"sure", nil];
    
    // 将逻辑定义到代码块里面
    void(^block)(NSInteger) = ^(NSInteger buttonIndex) {
        if (buttonIndex == 0)
        {
            NSLog(@"%ld",buttonIndex);
        }
        else
        {
            NSLog(@"%ld",buttonIndex);
        }
    };
    
    // 对象关联
    objc_setAssociatedObject(alert, &myAlerViewKey, block, OBJC_ASSOCIATION_COPY);
    
    [alert show];
}

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

执行效果如下:
Object - C运行时应用(2)—— 使用对象关联为分类增加属性(每个对象的属性互不干扰)
Object - C运行时应用(2)—— 使用对象关联为分类增加属性(每个对象的属性互不干扰)