我尝试接触 Runtime 时遇到很大的困难,
尽管尽力查阅各种文章, 却始终无法上手 Runtime
难点在于:
大多数文章对 Runtime 是什么, 在解决什么问题, 为什么如此设计一笔带过
着重在介绍 Runtime 本身, 里面有什么结构体, 什么函数, 什么字段
(比如消息传递流程, 一个简单的函数调用实现的极其复杂, 为什么这样?没解释)
这导致我能以背书的方式,
记忆结构体, 记忆里面的字段, 分析每个字段做的事情, 粗略搞懂某条流程
但接触的这些概念是 零散, 陌生的, 这导致每个新概念都可能引申出 2~3 个另外的新概念.
学习的各概念之间的联系非线性而随机, 导致了解一部分 与 冒出新概念 同时增加, 越看越懵
无法以宏观的方式, 将代码中每个部分建立联系, 理解某一部分代码在全局中的意义, 为什么被设计成这样
比如一个结构体, 有 A,B,C 三个字段:
- 为什么不设计 E,F,G 另外三个功能的字段
- A 字段目的是提供一个 hash 方便查找 IMP, 又引申出 IMP 这个新的概念
- A 字段所实现的功能, 在全局中是一个什么角色, 与其他部分是什么关系
举个例子:
struct objc_class 里 字段 cache
能知道的是, cache 是存放 SEL 的缓存, 作用是提高函数查找效率
难以理解的是,
- 为什么
objc_class要存SEL, SEL为什么能找到函数- 函数为什么需要查找,
cache在整个 Runtime 中是什么角色
后面的背景是:
struct objc_class cache 目的在于解决函数查询效率
↓
函数之所以需要查询原因在于 OC 的消息机制
↓
OC 用消息机制并且以动态的方式将其实现, 目的在于解决对象间的数据
↓
这源于 Alan Kay 面对当时数据共享造成的问题, 提出的面向对象 (着重于消息传递)的概念(后文会讲)
所以倒推回来:

1. 在 面向对象 被设计出来的那个年代, 程序为一系列的actions(procedures), 面临数据共享导致的耦合问题
2. Alan Kay 发明了 SmallTalk 用 面向对象 和 消息机制 解决问题
3. 一个对象互不共享状态的消息机制
4. 需要有运行时 的处理方式, 以及用于发送消息 objc_msgSend
5. 动态执行函数, 就需要有查找的凭据 SEL, 和可以调用函数的指针 IMP
6. 最终为了减少遍历, 就设计出了 cache
这让我往后看时不再有 知道的新内容 和 产生的陌生概念 同时增长的情况
以源头开始的优势在于, 树状结构的认识路线, 导致新认知的概念,都来源上一层.
子节点是对父节点的补充, 兄弟节点是共同实现父节点不同方面.
先有要解决的问题, 得出针对问题的设计方案, 先引申出联系, 再认识每部分的实现
一个收敛 — 逐步细化, 建立联系
而非发散 — 不断接触不同新概念
的认知过程