浅析Associated Object

Category是Objective C为程序员提供的一个强大的动态机制,它们允许程序员为已有的对象添加新的方法,即便是在没有该对象的源代码的情况下。通过它可以很方便的为已有的类来添加函数。但是Category不允许为已有的类添加新的属性或者成员变量。

通过运行时的数据结构我们可以看到,objc_class结构体中维护着objc_ivar_list的指针,这个指针指向的是类中定义的实例变量的列表。

再看看objc_category的结构体中,只有类别名,类名,实例方法,类方法和遵循的协议表,由此可以看出category类中是不能够添加成员变量的。

可以发现,苹果的category设计明显是不允许在category中添加新的成员变量。但是在项目中,这明显不能满足我们的需求,不过值得庆幸的是,我们可以通过Associated Objects来弥补这一不足。

Associated Objects 介绍

与 Associated Objects 相关的函数主要有三个,我们可以在 runtime.h 文件中找到它们的声明:

1. void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
2. id objc_getAssociatedObject(id object, const void *key)
3. void objc_removeAssociatedObjects(id object)

Object:传入关联对象的所属对象,也就是增加成员的实例对象,一般来说传入self。 key:一个唯一标记。在官方文档中推荐使用static char,当然更推荐是指针。为了便捷,一般使用selector,这样在后面getter中,我们就可以利用_cmd来方便的取出selector。 value:传入关联对象。 policy:objc_AssociationPolicy是一个ObjC枚举类型,也代表关联策略。

Associated Objects 源码浅析

那究竟关联对象是如何存储的呢?透过源码,我们看到关联对象是通过一个叫做AssociationsManager的对象来进行管理的。

在AssociationsManager中,有一个spinlock_t锁和一个AssociationsHashMap的哈希表。

然后再看objc_setAssociatedObject的源码,我们可以看懂啊AssociationsHashMap中的键为disguised_ptr_t,在得到这个指针的时候,源码中执行了DISGUISE方法,通过这个方法能够获得指向self地址的指针,即为指向对象地址的指针。然后其对应的value,便是一个存放关联对象的子哈希表。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏互联网杂技

JS模块与命名空间的介绍

起因 将代码组织到类中的一个重要原因是让代码更加“模块化”,可以在很多不同的场景中实现代码的重用。但类不是唯一的模块化代码的方式。 一般来讲,模块是一个独立的J...

3236
来自专栏calmound

sdut 1446 超级玛丽

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1446 题意:你...

2565
来自专栏后端技术探索

彻底掌握解释性语言&编译性语言,动态&静态语言

编译型和解释型的定义是对立存在的,但也可以在一个语言中同时存在。比如 java 语言同时兼有编译型和解释型特点。整个流程如下:

785
来自专栏技术博客

C#项目代码规范

   小菜就是小菜,几个人搞出来的项目,让公司大牛稍微看了下,最后送出了惨不忍睹四个字。命名各种各样,五花八门,大写英文、小写英文、大写拼音、小写拼音、英文和拼...

654
来自专栏君赏技术博客

颤抖吧!都在我的魔法下颤抖吧!--------我是 iOS 黑魔法师!

对于子类 B重写父类 A方法 method2在 iOS6.0之后才可以用是错误的,因为父类方法是可以在 iOS5.0就可以用的。

481
来自专栏柠檬先生

VUE 入门基础(6)

六,条件渲染   v-if 添加一个条件块     <h1 v-if=“ok”>Yes</h1>   也可以用v-else 添加else 块   <templa...

1879
来自专栏java一日一条

教你在Java接口中定义方法

接下来,SimpleTimeClient类实现了TimeClient接口,具体代码如下:

482
来自专栏前端知识分享

第68天:原型prototype方法

构造函数有一个prototype属性,指向实例对象的原型对象。通过同一个构造函数实例化的多个对象具有相同的原型对象。经常使用原型对象来实现继承

762
来自专栏杂七杂八

列表、字典、集合中筛选数据

传统迭代法 data = [1,5,-3,-2,8,0,9] res = [] for x in data: if x >=0: res...

3426
来自专栏三丰SanFeng

写出完美的snprintf

平时公司的代码安全扫描会给出不安全代码的告警,其中会检查代码中间的strcpy和sprintf函数,而要求使用strncpy和snprintf。今天我们讨论一下...

1915

扫码关注云+社区