iOS runtime总结数据结构,消息传递、转发和应用场景

runtime篇

首先看一下runtiem底层的数据结构

首先从objc_class这么一个结构体(数据结构)开始,objc_class继承于objc_object。

objc_object当中有一个成员变量叫isa_t,那么这个isa_t指针就指向一个objc_class类型的类对象(或者说元类对象)。

objc_class主要包含三个成员变量,superClass(指向当前类的父类)、cache_t(用来提供消息传递过程中的缓存方法查找)、class_data_bits_t(类的一些基本信息:类所定义/通过分类所添加 的成员变量,属性,方法列表都在这个数据结构中)

superClass:实际是class类型的,它指向objc_class类型的这样一个指针

cache_t:实际上是装满了bucket_t数据结构的Hash表,维护的也就是这个hash表

class_data_bits_t:实际上是对class_rw_t的数据结构的封装class_rw_t中包含了(class_ro_t类相关的只读信息、protocols类分类中的协议、properties类分类中的属性、methods类分类中的方法)

class_ro_t包含了name类名、methodList类的方法列表--method_t、ivars声明的类的成员变量、类的属性、类的协议。

Runtime基础数据结构如下: objc_object、objc_class、isa指针、method_t

下面讲一下runtime的根元类

objc_object

即id类型(我们平时用的所有对象都是id类型的,在runtime中,id 就是 objc_object结构体)

objc_object结构体主要包含:

1.isa_t:共用体。

2.关于isa操作相关的一些方法:通过objc_object结构体,来获取isa所指向的类对象,或者通过类对象的isa指针获取它的元类对象一些遍历的放大。

3.弱引用相关:标记一个对象是否曾经有过弱引用指针。

4.关联对象相关方法:我们为对象设置了关联属性,关于关联属性的一些相关方法也体现在objc_object结构体中。

5.内存管理相关的方法实现:MRC下经常用到的runtain,release等方法实现 ,以上均封装在objc_object结构体中

objc_class

OC中的Class,代表一个类,他在runtime中对应objc_class的数据结构(结构体)。

objc_class继承objc_object

所以Class这样一个类也是一个对象,称为类对象,因为它继承自objc_object。

objc_class包含:

1.objc_class拥有一个superClass指针,指向class类型,(如果说Class是一个类对应的话,superClass指针指向的就是它的父类对象,就是我们平时说的类与父类,实际上是通过objc_class中superClass成员变量来定义的)。

2.cache_t cache成员变量: 方法缓存结构,消息传递时会使用这样的数据结构。

3.class_data_bits_t bits数据结构: 关于类所定义的变量,属性,方法都在bits这样一个成员结构中。

isa指针

它是C++中的共用体,在OC中名称是isa_t

不论是64位架构上(或者32位架构)上面,共用体是64个(或者32个) 0或者1的数字 (按大多数64位分析)

分两种类型(isa指针是什么含义的时候):

1.指针型isa: 64位的0或者1的整体内容代表所指向的Class的地址,也就是可以通过isa的内容来获得类对象的地址。

2.非指针型isa: isa的值得部分代表Class的地址,之所以这样是因为我们在寻址过程中,只有三四十位数就可以保证我们寻找到所有Class地址了,多出来的位可以用来存储其他相关内容,来达到节省内存的目的。

isa的指向:

关于对象,它指向类对象

例如我们拥有一个实例,实例就是OC中对应的id类型,在Runtime中就是objc_object,里面有个isa指针,会指向它对应的Class。

关于类对象,指向元类对象

class因为集成objc_object,所以里面也有isa指针,指向其元类对象。

当我们进行方法调用时,调用一个实例的实例方法,实际上是通过isa指针,到它的类对象中,去进行方法查找。

如果我们调用的是类方法,那么是通过类对象的isa指针,到它的元类对象中去查找。

cache_t

是用于快速查找方法执行函数的一个结构(当我们调用一个方法时,如果有缓存,我们就不需要去方法列表中遍历了,可以提高方法调用速度)。

是可增量扩展的哈希表结构(当结构存储量增大的过程中, cache_t会增量扩大它的内存空间来支持更多的缓存,用哈希表实现这个数据结构,是为了提高查找效率)。

cache_t数据结构是计算机局部性原理的最佳应用(计算机局部性原理:在一般调用方法时,有几个方法调用频次较高,把他们放到方法缓存中,下次的命中率就会更高)。

cache_t具体数据结构说明:

可以理解为是数组来实现的

每个对象都是bucket_t这样的一个结构体, bucket_t有两个主要成员变量,key和IMP。key对应OC中的selector,在调用方法时是个选择器SEL。

IMP理解为无类型的函数指针,可以通过方法选择器的名称key来寻找这个方法的具体实现IMP。

假如现在有个key,可以通过哈希查找算法来定位当前key所对应的bucket_t位于数组当中哪个位置,然后从这个位置中提取出bucket_t中的IMP

class_data_bits_t

这个结构是objc_class中的成员结构

class_data_bits_t主要是对class_rw_t的封装。

class_rw_t代表了类相关的读写信息,例如给类添加的分类的一些方法,属性以及协议等,同时它也对class_ro_t的封装,我们可以随时创建分类,为类增加属性或者方法。rw是readWrite的简写,ro是readOnly的意思,创建类时,添加的成员变量或方法列表在之后就没办法修改了

class_ro_t代表了类相关的只读信息。

包含

1.class_ro_t

2.protocols类分类中的协议

3.properties类分类中的属性

4.methods类分类中的方法

这三个数据结构是个二维数组

假如我们三个分类A、B、C,编译顺序A->B->C。这时会逆序遍历并打包成分类数组,分类C中的所有方法都在第一列竖列表中,存在二维数组的第1项。分类B中的所有方法都在第二列竖列表中,存在二维数组的第2项。分类A中的所有方法都在第三列竖列表中,存在二维数组的第3项。

1.name:类名

2.ivars:声明的类的成员变量

3.类的属性

4.类的协议

5.类的方法列表

除1外都是一维数组

在方法列表当中存储的内容,一般是分类中添加的方法

method_t实际上是对方法的抽象说明

method_t

method_t是对函数四要素(名称、返回值、参数、函数体)的封装

函数四要素决定了函数的唯一性

method_t是个结构体,主要有三个数据类型

1.name函数名称

2.types 函数返回值和参数的集合

3.imp 无类型的函数指针,对应着函数体

苹果的Type Encodings技术

types成员属性,实际上表达结构是:

第一个位置永远是函数的返回值类型,后面跟着每个参数的参数类型

参数可以有多个,返回值只有一个

V@:代表types所存储的内容

V对应返回值,@对应参数1,:对应参数2

二、消息的转发机制

https://github.com/LeesimEverglow/LMMessageForwardDemo demo地址

参考资料:https://www.jianshu.com/p/fdd8f5225f0c

消息转发机制共分为3大步骤:

1.Method resolution 方法解析处理阶段处理对象或者类本身是否能响应某方法

2.Fast forwarding 快速转发阶段,某对象的属性中也许该包含了其他类对象,但是这个类对象是否能响应该方法呢,则是快速转发

3.Normal forwarding 常规转发阶段 如果都不能响应,则会创建一个虚基类来看是都能接收,看虚基类能否响应该方法的签名,如果不能则最后抛出异常。

1.消息的转发和替换其实大面积有效的可以使用在混淆上面,让方法名进行混淆,代替执行。比如热更新的混淆

2.可以实现多重代理,让不同对象可以同时代理同个回调,然后在各自负责的区域进行相应的处理,降低了代码的耦合程度。

3.间接实现多继承Objective-C本身不支持多继承,这是因为消息机制名称查找发生在运行时而非编译时,很难解决多个基类可能导致的二义性问题,但是可以通过消息转发机制在内部创建多个功能的对象,把不能实现的功能给转发到其他对象上去,这样就做出来一种多继承的假象。转发和继承相似,可用于为OC编程添加一些多继承的效果,一个对象把消息转发出去,就好像他把另一个对象中放法接过来或者"继承"一样

三、消息的传递机制 (消息动态绑定机制)

参考:https://juejin.cn/post/6844904014669152270

四、runtime的实际应用

参考:https://www.jianshu.com/p/d761d5938c77
© 著作权归作者所有,转载或内容合作请联系作者

喜欢的朋友记得点赞、收藏、关注哦!!!

相关推荐
man201743 分钟前
基于Springboot+Mysql的闲一品(含LW+PPT+源码+系统演示视频+安装说明)
java·spring boot·后端·mysql
写bug写bug1 小时前
在Spring Boot中优雅的计算方法执行时间
java·spring boot·spring
写bug写bug1 小时前
掌握 Spring 中的 WebClient
java·后端·spring
麓殇⊙1 小时前
spring--整合Mybatis详解
java·spring·mybatis
你们补药再卷啦2 小时前
springboot 项目 jmeter简单测试流程
java·spring boot·后端
喵手3 小时前
Spring Boot 项目基于责任链模式实现复杂接口的解耦和动态编排!
spring boot·后端·责任链模式
caihuayuan54 小时前
redis linux 安装简单教程(redis 3.0.4)
java·大数据·spring boot·后端·课程设计
Lonely丶墨轩4 小时前
IDE中使用Spring Data Redis
ide·redis·spring
金融数据出海6 小时前
Spring Boot对接马来西亚股票数据源API
java·spring boot·后端·金融