【iOS基础】关联对象

2018-08-07  本文已影响11人  亲爱的大倩倩
关联对象含义

关联对象是指某个OC对象通过一个唯一的key连接到一个类的实例上,这么听起来可能有点难理解,看看他有什么用处就知道了
1.在分类中添加属性
2.是将两个对象相互关联,让一个对象保持对另一个对象的引用并获取那个对象

还有一种比较好理解的说法,就是给A(可能是类可能是控件)关联一个值,也可能是关联一个属性,那么到用的时候取出来直接用就行了

下面这句话,相当于给btn添加了一个值为1,通过limitKey将他俩连在了一起
objc_setAssociatedObject(btn, limitKey, @"1", OBJC_ASSOCIATION_ASSIGN);
当用的时候直接这样,那么flag的值就是1
NSString *flag = objc_getAssociatedObject(btn, limitKey);
关联对象如何使用
进行关联对象,后面参数表示:原对象,关键字,关联的对象,关联策略
objc_setAssociatedObject(id_Nonnull object, constvoid * _Nonnull key, id_Nullable value, objc_AssociationPolicy policy)
OBJC_ASSOCIATION_ASSIGN = 0,      <指定一个弱引用关联的对象>
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,<指定一个强引用关联的对象>
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,  <指定相关的对象复制>
OBJC_ASSOCIATION_RETAIN = 01401,      <指定强参考>
OBJC_ASSOCIATION_COPY = 01403    <指定相关的对象复制>
###关联对象的方法
1.直接用@selector(方法名)关联
objc_setAssociatedObject(self,@selector(btnAction:) , block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
btnBlock block = objc_getAssociatedObject(self,@selector(btnAction:));
2.声明static对象,使用时用&对象进行关联
staticconstchar btnKey;
objc_setAssociatedObject(self, &btnKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
btnBlock block = objc_getAssociatedObject(self,&btnKey);

###获取关联的对象
objc_getAssociatedObject(id_Nonnull object, constvoid * _Nonnull key)

###当我们不需要关联时,移除关联
void objc_removeAssociatedObjects(id object)
或者objc_setAssociatedObject设为nil
举例1:分类中添加属性

category不能添加实例变量,会直接报错,因为实例变量所在的内存区域在类初始化时已经定了,不可更改,我们无法在动态运行时时添加

category可以增加属性, 但属性不会自动生成成员变量, 也不会自动生成 getter/setter 的实现,需要自己实现
若自己不实现set/get,在VC中调用和在类别中调用在代码时不会报错,但是编译后会报错

怎么才能让分类中的属性正常使用呢,我们可以根据runtime的关联对象功能来添加

这里说的关联对象是指某个OC对象通过一个唯一的key连接到一个类的实例上,内部目前我不清楚,但我猜是关联后就在类的存储空间里强行安了个_header的实例变量吧,这样就可以让我们使用了,同时也相当于官方的UIScrollView多了个header的属性


一.UIScrollView类别中声明属性,并在属性的set和get方法里面设置属性和类别的关联
@interface UIScrollView (TBRefresh)
@property(nonatomic,weak)TBRefreshHeadView *header;
-(void)setHeader:(TBRefreshHeadView *)header
{
   objc_setAssociatedObject(self, @selector(header), header, OBJC_ASSOCIATION_ASSIGN);
}
-(TBRefreshHeadView*)header
{
     returnobjc_getAssociatedObject(self, @selector(header));
}
二,在内部和外部VC中正常使用这个属性
类别中: self.header = TBheader;
VC中:   NSLog(@"输出的这个是什么%@",_mainTableview.header);
举例2: 将两个对象相互关联,让一个对象保持对另一个对象的引用并获取那个对象
一.设定关联.将indexPath关联到alert
#import <objc/runtime.h>
staticchar kUITableViewIndexKey;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"提示"
                                                    message:@"这里是xx楼"
                                                   delegate:self
                                          cancelButtonTitle:@"好的"
                                          otherButtonTitles:nil];
    objc_setAssociatedObject(alert, &kUITableViewIndexKey, indexPath, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [alert show];
}
二.通过获取关联对象来获取到indexPath信息
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if (buttonIndex == 0)
    {
        NSIndexPath *indexPath = objc_getAssociatedObject(alertView, &kUITableViewIndexKey);
        NSLog(@"%@", indexPath);
    }
}
上一篇下一篇

猜你喜欢

热点阅读