本文转载请注明出处——polobymulberry-博客园

两个函数名称中都有associate,意思是关联,这里的关联表示的是一种 从属关系,即有一个关联者被关联者,我们说NSArray的对象array关联了NSString对象string,这里的array就是关联者(表示主动关联别人),string就是被关联者(表示被动被别人关联)。我们就会产生三个哲学问题。

  1. 关联是什么?
  2. 为什么关联?
  3. 怎么关联?

既然关联是要有关联者被关联者,我们可以看到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中关联的方法可以做很多事,网上一搜一大把。我觉得首先明白这两个函数是做什么的,至于怎么用,什么最佳实践,还是去实践中体会了。

【原】objc_setAssociatedObject和objc_getAssociatedObject的更多相关文章

  1. [Objective-C]关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)

    关联 关联是指把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分.    关联特性只有在Mac OS X V10.6以及以后的版本上才是可用的. 在类的定义之外为类增加额外的存储空间 ...

  2. [Objective-C]关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)(转)

    转载自:http://blog.csdn.net/onlyou930/article/details/9299169 分类: Objective-C2013-07-11 11:54 3420人阅读 评 ...

  3. ios扩展机制objc_setAssociatedObject,objc_getAssociatedObject

    这个可以解决变量传递问题, 就不用定义全局的了. 使用例子: 首先导入头文件:#import <objc/runtime.h> 设置静态常量:static char alertinfoke ...

  4. iOS swift objc_setAssociatedObject和objc_getAssociatedObject使用

    oc中的AssociationsManager在swift中也是可以实现的 使用方法请看下面一个例子 import UIKit extension UIButton { func fk_addActi ...

  5. iOS - Objective-C 关联(objc_setAssociatedObject、objc_getAssociatedObject、objc_removeAssociatedObjects)

    关联是指把两个对象相互关联起来,使得其中的一个对象作为另外一个对象的一部分. 关联特性只有在Mac OS X V10.6以及以后的版本上才是可用的. 在类的定义之外为类增加额外的存储空间 使用关联,我 ...

  6. objc_setAssociatedObject 1

    [Objective-C]关联(objc_setAssociatedObject.objc_getAssociatedObject.objc_removeAssociatedObjects) 标签:  ...

  7. iOS Objective-C对象模型及应用

    前言 原创文章,转载请注明出自唐巧的技术博客. 本文主要介绍Objective-C对象模型的实现细节,以及Objective-C语言对象模型中对isa swizzling和method swizzli ...

  8. iOS 消息发送与转发详解

    Objective-C 是一门动态语言,它将很多静态语言在编译和链接时期做的事情,放到了运行时来处理.之所以能具备这种特性,离不开 Runtime 这个库.Runtime 很好的解决了如何在运行时期找 ...

  9. iOS Class结构分析

    objc_class结构体 类在OC中是objc_class的结构体指针 typedef struct objc_class *Class; 在objc/runtime.h中objc_class结构体 ...

随机推荐

  1. 分布式系列文章——Paxos算法原理与推导

    Paxos算法在分布式领域具有非常重要的地位.但是Paxos算法有两个比较明显的缺点:1.难以理解 2.工程实现更难. 网上有很多讲解Paxos算法的文章,但是质量参差不齐.看了很多关于Paxos的资 ...

  2. CMS模板应用调研问卷

    截止目前,已经有数十家网站与我们合作,进行了MIP化改造,在搜索结果页也能看到"闪电标"的出现.除了改造方面的问题,MIP项目组被问到最多的就是:我用了wordpress,我用了织 ...

  3. 一次修改闭源 Entity Provider 程序集以兼容新 EntityFramework 的过程

    读完本文你会知道,如何在没有源码的情况下,直接修改一个 DLL 以去除 DLL 上的强命名限制,并在该程序集上直接添加你的“友元程序集(一种特殊的 Attribute,将它应用在程序集上,使得程序集内 ...

  4. 2.WindowsServer2012R2装完的一些友好化设置

    网站部署之~Windows Server | 本地部署 http://www.cnblogs.com/dunitian/p/4822808.html#iis 1.桌面图标(控制面板里面屏蔽了,得自己输 ...

  5. HTML5 语义元素(一)页面结构

    本篇主要介绍HTML5增加的语义元素中关于页面结构方面的,包含: <article>.<aside>.<figure>.<figcaption>.< ...

  6. 步入angularjs directive(指令)--准备工作熟悉hasOwnProperty

    在讲解directive之前,先做一下准备工作,为何要这样呢? 因为我们不是简单的说说directive怎么用,还要知道为什么这么用!(今天我们先磨磨刀!). 首先我们讲讲js 基础的知识--hasO ...

  7. [systemtap手记]debian体系安装过程

    Debian体系,本人测试用机 Ubuntu 11.10 uname -r 查看原本的内核版本为 3.0.0-12-generic 第一步: 安装systemtap包 $ sudo apt-get i ...

  8. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  9. 【干货分享】流程DEMO-制度发文和干部任免

    流程名: 制度发文和干部任免  业务描述: 当员工在该出勤的工作日出勤但漏打卡时,于一周内填写补打卡申请.  流程相关文件: 流程包.xml  流程说明: 直接导入流程包文件,即可使用本流程  表单: ...

  10. 易用BPM时代,企业如何轻松驾驭H3?

    众所周知,BPM作为企业发展的推动力,能敏捷高效的融合业务流程和信息资源.通过综合考虑流程的成本.效率.质量等方面因素,用IT系统将调整后的流程固化下来,从而降低企业管理成本,提高内部运营效率,提升企 ...