Runtime系列(浅析数据结构)
2023-04-18 15:00:17 时间
上篇文章说到类与元类,我们已经知道类的本质是结构体objc_class,接下来看看objc_class是什么
objc_class.png
isa指向元类,super_class表示当前类的父类,这两个成员我们已经很熟悉,这里不再赘述(可参考 类与元类 、 引文)。
name:类名
version:版本相关信息,默认为0
info:提供运行期使用的标示符
instance_size:当前类实例变量的大小(包括父类)
- ivars
从objc_class可以看到,ivars是结构体objc_ivar_list的指针
objc_ivar_list and objc_ivar.png
结构体各成员见名知意,不再逐个解释。可见,ivars其实是一个存储类中成员变量相关信息的链表。
其中
Ivar.png
- methodLists
从objc_class可以看到,methodLists是结构体objc_method_list的二级指针
objc_method_liist and objc_method.png
又见结构体的自嵌套,可见methodLists也是链表,存储类中的方法相关信息。由于是二级指针,所以可以动态修改类中的方法,这也是分类的实现原理。
其中
Method.png
这里要解释一下SEL和IMP:
- SEL
- 什么是SEL
SEL是对方法的包装,常见的定义有SEL sel1 = @selector(message1); SEL sel2 = NSSelectorFromString(message2);
- 为什么要对方法进行包装
获取方法所对应的ID - 什么是方法对应的ID
可以理解为方法名的一种映射
- 什么是SEL
来看下面的例子
- (void)helloWorld:(int)flag; - (void)helloWorld:(float)flag;
在OC中,这样写会报错,错误类型为重复声明。如果这样写:
- (int)helloWorld:(int)flag; - (float)helloWorld:(float)flag;
即使返回值不同,仍然是重复声明。因为他们的方法名相同,都是helloWorld:,所以这四个方法对应着同一个SEL。
不过这是在同一个类中,如果是不同的类呢?
无论是在同一个类还是在不同的类,只要方法名相同,SEL就相同,获取的ID就相同。
既然方法名相同ID就相同,如果两个非继承关系的类存在相同方法名的方法,那该如何确定执行那个类中的方法?
再来回顾引文提到的函数
id objc_msgSend(id self, SEL op, ...)
[receiver message]还有个接受者,即使ID相同,不同的接收者定位到的方法仍然不同,而各类中不允许存在相同方法名的方法,这样就确定了***性。
- IMP
相比于SEL,IMP要爽快得多。IMP的本质是函数指针,直接通过IMP就可以找到各个方法。这样效率更高,因为绕过了消息传递阶段,直接定位。
回到objc_class。
cache和protocols不再深入,这里只做简单介绍
- cache
cache同样是链表,存储曾经调用过的方法的相关信息,这样将常用方法存到cache中,可以提高方法的查找效率。 - protocols
protocols仍然是链表,存储当前类(包括父类)遵守的协议的相关信息。
相关文章
- 一个Java程序员对2011年的回顾
- 大数据发展历程
- Android高级进阶之路【一】Android中View绘制流程浅析
- 可信服务管理(Trusted Service Manager)介绍
- GIS应用|快速开发REST空间分析服务
- 未来十年微软长盛不衰的两项战略
- 领域驱动设计模式的收益与挑战
- cocos 3.0 一键打包android平台应该注意的细节
- 数智化时代,驱动企业转型升级的“三驾马车”是什么?
- 基于MINA构建高性能的NIO应用
- 使用Rainbond实现离线环境软件交付
- 工作流引擎 jBPM 5.2 发布
- 微信小程序Minium自动化测试(三)
- 桌面应用抢先体验,这次有点料!
- 甲骨文Java专利遭拒 起诉Android侵权受挫
- 云计算的应用领域及发展前景
- Java效率真的很低吗?Android为何要采用?
- Android高级进阶之路【二】十分钟彻底弄明白 View 事件分发机制
- 庖丁解牛之-Android平台RTSP|RTMP播放器设计
- 手机直付,超级方便