一.AssociatedObject
1.大家在iOS的学习和实战过程中往往会遇到一些相对来说深奥一点的语法.而今天在这里将会给大家叙述关于 AssociatedObject的基本运用:objc_getAssociatedObject && objc_setAssociatedObject
2.说句实在话,我也是一个刚入行的小菜鸟,如果有写的不对的地方,请大家海涵和指点.(废话到此为止,直接上代码和注释)
二. 导入头文件
1. objc/runtime.h
下面是一个数组, 和一个字符串
NSArray *arr = [[NSArray alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
NSString *overView = [NSString stringWithFormat:@"%@,%@",@"five",@"six"];
调用方法1: 设置关联对象
objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)
- 1.第一个参数:
id object
: 需要传入的是 : 对象的主分支 - 2.第二个参数:
const void *key
: 是一个 static 类型的 关键字,这里根据开发者自身来定义就行(尽量写的有根据一点,避免以后忘记是干啥用的) - 3.第三个参数:
id value
: 传入的是: 对象的子分支 - 4.第四个参数:
objc_AssociationPolicy policy
:是当前关联对象的类型 strong,weak,copy (枚举类型:开发者可以点进去看)
①类的主分支
:如果将一个label控件和控制器关联上,而且放在控制器上面,那么这个控制器对象 self 或者 self.view 就充当 主分支
②子分支
: 那么这个label 就充当 子分支
③如果 控制器上有两个控件, 一个Label, 一个 View, 那么想这两个控件 弄上关联关系, 这两个控件随意一个做主分支,一个做子分支(这个根据开发场景而定)
2.如何确定主分支和子分支
如果子分支内存被释放了, 主分支没有释放, 那么可以通过 objc_getAssociatedObject获取到 子分支(虽然它被释放了,但是一样可以获取到) . 如果主分支被释放了,子分支没有释放, 则获取不到任何一个对象
调用方法2: 获取关联对象
objc_getAssociatedObject(<#id object#>, <#const void *key#>)
就相对来说容易理解一点了
- 1.第一个参数 : 主分支
- 2.第二个参数 : 关键字
三.代码和注释
下面有讲到 解除关联对象, 以及 删除关联对象 objc_removeAssociatedObjects
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *arr = [[NSArray alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
NSString *overView = [NSString stringWithFormat:@"%@,%@",@"five",@"six"];
// 设置关联对象
objc_setAssociatedObject(arr, &overViewKey, overView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// NSLog(@"%@==%@",arr,overView); // 正常打印结果 ,如果arr 没有被释放,就算overView被释放了, 也可以用到 overView.因为它们两关联起来了
// 上面已经将 arr 和 overView 关联上了, 在这里 通过 objc_getAssociatedObject :arr , 和关键字 overViewKey ,将关联对象获取出来
NSString *associatedObj = objc_getAssociatedObject(arr, &overViewKey);
NSLog(@"associatedObj:%@",associatedObj); // 打印结果: associatedObj:five,six
// 释放 关联对象
// 第三个参数, 设为 nil, 则将 arr 与 nil 关联... 也等同于 : 没关联任何对象
objc_setAssociatedObject(arr, &overView, nil, OBJC_ASSOCIATION_ASSIGN);
// 移除 所有关联对象 : 这个方法 相当于 初始化 arr 对象一样(并不是初始化arr这个指针所指向的内存地址)
objc_removeAssociatedObjects(arr);
}
四.看到别人代码块里头会用到 _cmd 这个关键字
此关键字代表的是什么?
- (UILabel *)textLabel{
return objc_getAssociatedObject(self, _cmd);
}
上面代码 直接通过 objc_getAssociatedObject
方法获取到 textLabel 关联的关键字, 或者 对象本身 或者 Bool 等等
而关键在于下面一个句代码:
- (void)setTextLabel:(UILabel *)textLabel{
objc_setAssociatedObject(self, @selector(textLabel), textLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
_cmd
:第一句返回的时候,相当于返回一个 id对象 ,而关键字则是 : textLabel ,它是根据当前方法,直接使用方法的名称,即 - (***)textLabel 方法,并且能保证改名称不重复.(第一句代码方法名 : textLabel ,因为一个类中不可能用相同的方法名)
第二句代码中出现 @selector(textLabel)
,这里它就调用第一句代码了, @selector
直接返回SEL,则获取到textLabel的方法名,则为第一句代码返回的值.
// 1.直接口述代码吧.
// 2.上面两个方法 写在一个 单独的View中,在这个类的 .h中,创建一个 weak(若引用)的textLabel,而在.m文件中 initWithFrame中直接创建self.textLabel = [[UILabel alloc] initWithFrame:self.bounds];并添加到这个view上
// 3.那么按照常理来说, 这里应该报警告, 但是 在控制器中打印 这个类的 textLabel , 你会发现是有内存的, 如果把第一句和第二句代码注释掉, 打印则没有内存.
网友评论