【原】objc_setAssociatedObject和objc_getAssociatedObject
2015-11-27 13:42
603 查看
本文转载请注明出处——polobymulberry-博客园
两个函数名称中都有associate,意思是
关联是什么?
为什么关联?
怎么关联?
既然关联是要有
OBJC_EXPORT 打包lib时,用来说明该函数是暴露给外界调用的。
主要看该函数的几个参数:
id object 表示关联者,是一个对象,变量名理所当然也是object
id value 表示被关联者,我们可以看到它的变量名是value,我们这里一定要理解
关联者和被关联者有了,那么又会产生两个问题,而答案正好对应函数的另外两个参数。
一个就是我
你看,只需要一个object(关联者)和一个key来获取关联。这里我主观臆测此处一个关联者的关联关系使用
另外,这个被关联的对象也是要存在内存中的,那它的内存管理方式如何?
objc_AssociationPolicy policy
它是一个枚举,具体如下
这个字面上看是指关联策略,但是这里的策略更注重关联关系的
比如我们使用
相当于string是array的一个retain属性,嗯。。。你可以理解为strong。所以当array销毁时,string也自然就不存在了。
上面看懂了,使用就很方便了。举个最简单的例子,把一个NSString对象关联到NSArray对象上。
输出结果
当然,oc中关联的方法可以做很多事,网上一搜一大把。我觉得首先明白这两个函数是做什么的,至于怎么用,什么最佳实践,还是去实践中体会了。
两个函数名称中都有associate,意思是
关联,这里的关联表示的是一种
从属关系,即有一个
关联者和
被关联者,我们说
NSArray的对象array关联了NSString对象string,这里的
array就是
关联者(表示主动关联别人),
string就是
被关联者(表示被动被别人关联)。我们就会产生三个哲学问题。
关联是什么?
为什么关联?
怎么关联?
既然关联是要有
关联者和
被关联者,我们可以看到
objc_setAssociatedObject这个函数,就是为了设定关联关系,说简单点,就是为了把两个对象关联起来。
// objc_setAssociatedObject函数原型 OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
OBJC_EXPORT 打包lib时,用来说明该函数是暴露给外界调用的。
主要看该函数的几个参数:
id object 表示关联者,是一个对象,变量名理所当然也是object
id value 表示被关联者,我们可以看到它的变量名是value,我们这里一定要理解
这个value最后是要关联到object上的。
关联者和被关联者有了,那么又会产生两个问题,而答案正好对应函数的另外两个参数。
一个就是我
日后如何获取这个关联关系,也就是说,我今后要使用这个关联关系,如何获取?有人会说我直接使用根据object(关联者)来获取不就行了,但是一个object可能有许多被关联者,比如上面的NSArray可以关联一个NSString,也可以关联一个NSDictionary。有人说那直接用关联者和被关联者两个去获取不就行了。但是使用一个关键词key(一般是一个字符串),更合适。因为字符串可以写成全局的,这样可以在各个地方都自由获取到关联的对象了。而如果直接使用关联的对象来索引,并且当这个关联对象是局部变量时,那么在别的函数中要获取的时候,就很麻烦了,此时你要不然就写成全局的,那样代码将很乱,所以我觉得统一使用字符串来索引关联关系更合适。我们看看apple是怎么设计
获取关联的方法:
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
你看,只需要一个object(关联者)和一个key来获取关联。这里我主观臆测此处一个关联者的关联关系使用
hashtable来表示的(
我猜测的,还未深入研究,大神请拍砖)。根据
objc_getAssociatedObject的参数,我们理所当然就会在set函数中使用一个key来表示关联关系了。大概就像下面这样:
另外,这个被关联的对象也是要存在内存中的,那它的内存管理方式如何?
objc_setAssociatedObject函数中还有一个参数是
objc_AssociationPolicy policy
它是一个枚举,具体如下
enum { OBJC_ASSOCIATION_ASSIGN = 0, OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, OBJC_ASSOCIATION_COPY_NONATOMIC = 3, OBJC_ASSOCIATION_RETAIN = 01401, OBJC_ASSOCIATION_COPY = 01403 };
这个字面上看是指关联策略,但是这里的策略更注重关联关系的
内存管理方面。我们这里可以大胆意淫,这个被关联者value其实很像object的一个属性(property),当然,我们还可以扩展方法。看到这里,有人可能会说这不就是category吗?可以说是,也可以说不是。是的原因是它们都扩展了OC对象的属性,不是的原因是category是
编译时就决定了扩展的属性,而objc_setAssociatedObject是
运行时来扩展属性。
比如我们使用
objc_setAssociatedObject(array, &key, string, OBJC_ASSOCIATION_RETAIN);
相当于string是array的一个retain属性,嗯。。。你可以理解为strong。所以当array销毁时,string也自然就不存在了。
上面看懂了,使用就很方便了。举个最简单的例子,把一个NSString对象关联到NSArray对象上。
#import "ViewController.h" // 使用objc_getAssociatedObject和objc_setAssociatedObject // 需要添加objective-c的运行时文件 #import <objc/runtime.h> // 表示关联关系的key,主要目的是用来索引 const NSString *associatedKey = @"associate_nsarray_with_nsstring_key"; @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSArray *array = [NSArray arrayWithObjects:@"hello", @"world", @"!", nil]; NSString *string = @"I am an iOS developer!"; // 将string关联到array上 objc_setAssociatedObject(array, &associatedKey, string, OBJC_ASSOCIATION_RETAIN_NONATOMIC); // 从array中获取被关联的对象string // 注意,这里就没有string这个对象任何事了 // string其实已经变成了array的一个属性值 NSString *getAssociatedObject = objc_getAssociatedObject(array, &associatedKey); NSLog(@"%@", getAssociatedObject); } @end
输出结果
当然,oc中关联的方法可以做很多事,网上一搜一大把。我觉得首先明白这两个函数是做什么的,至于怎么用,什么最佳实践,还是去实践中体会了。
相关文章推荐
- sumline text 正则匹配
- Object
- IOS开发基础Object-C(10)—OC内存管理(4)-autorelease使用
- Objective-C RunTime机制(1)
- 在ObjectARX中添加“块”
- 用递归方式解析JSONObject 为HashMap
- Objective C 链式调用
- objective-c 关键字和概念
- Objective-C 字符串
- iOS高效开发必备的10款Objective-C类库
- Objective-C 工厂方法
- Objective-C set/get方法
- 102 For which two database objects can the VERSIONS clause of the Flashback Versions Query be used?
- Swift如何调用Object-C类
- 如何在Objective-C中实现链式语法?
- Objective-C 类,函数调用
- 【读书笔记一】Zen and the Art of Objective_C Craftsmanship
- OC基础
- 92 Examine the output of the query that you executed to list the objects in the recycle bin: SQL> SE
- PHP反射类ReflectionClass和ReflectionObject的使用方法