ios底层核心模板结构 - list_array_tt entsize_list_tt
探索objc底层原理过程中,经常会碰到一个模板 list_array_tt
你在类加载,方法查找,散列表,同步锁等等都会碰到这个结构,c++的模板功能十分强大,但代码看上去确实比较头疼
其实没那么糟了,我们可以尝试了解下这个结构,对探索ios底层源码很有帮助,如果不以模板的角度去考虑,那么在分析源码的过程中,很多逻辑就会想淡然,底层的理解上就会止步不前
初步预览 list_array_tt
list_array_tt 是个模板,存在于runtime头文件中,可见它对于runtime api的重要性了
最简单粗俗理解,从模板命名看,List Element,逻辑上就是一个容器List 与 元素Element的关系,不过不是简单的线性关系
list_array_tt 鸟瞰结构
一个array_t 结构体
一个迭代器
一个list指针,不过比较特殊,它还有一个附加功能,可以表述数组
list_array_tt 关键方法整理
hasArray() 是否有数组功能
array() 返回数组容器
setArray(array_t *array)
count() 元素数量
begin() end() … 迭代器迭代功能
countLists() 数组array的元素list的数量 也就是有多少个list
beginLists() endLists() 第一个list 与 最后一个list
attachLists(List* const * addedLists, uint32_t addedCount) array添加list逻辑
很重要
预览 entsize_list_tt
entsize_list_tt 也是个模板,也存在于runtime 头文件中
entsize_list_tt 鸟瞰结构
entsizeAndFlags 除了记录元素大小,同时额外比特位包含flag信息
count 可以粗俗理解为模板元素的数量
也有一个迭代器
entsize_list_tt 关键方法整理
entsize() 元素大小
get(uint32_t i) 获取元素
byteSize() 模板List字节大小
begin() end() 迭代器迭代功能
此处发现有个迭代器,list_array_tt也有个迭代器,会感觉烦乱,后面我会拆解
entsize_list_tt 迭代分析
迭代器iterator是个内部结构体 内部结构
entsize 迭代元素大小
index 索引 主要是重载运算符号 中使用
element 迭代元素指针
迭代器iterator的迭代功能其实很简单,主要通过运算符号重载实现迭代器的 ++ – *取元素 ->取元素指针 ==判断元素相等 != > < 比较大小
operator 重载符号 是c++的重载运算符的语法,就是把运算符重载为迭代器的函数,运算符当作函数,通过传惨调用函数 实现迭代过程中的运算逻辑
自增1 自减1 都是通过迭代器当前元素指针偏移 指针节点个数来实现的,可以对照链表偏移节点那样去理解 但你再仔细看下,这是内存偏移
可以简单猜测一下 此处的迭代器 在 list_array_tt中也会使用到,先不用考虑list_array_tt中的迭代器结构,从鸟瞰代码预览中,大致已经知道 list_array_tt 是个两层嵌套结构
list_array_tt 双层嵌套结构
外层可以类似看作是个数组结构,数组元素为模板List
模板List是内层结构,作为 list_array_tt的一个元素,而前面提到的迭代器主要是为了迭代List模板容器中的元素而创建的
对于 list_array_tt中的迭代器,相信最终调用的还是 此处entsize_list_tt中的迭代器
回到 list_array_tt
list_array_tt 中的迭代器分析
可能会有人觉得这个List::iterator 理解起来有点困难
其实这个List就是模板 entsize_list_tt ,这么说可能还是有点迷糊 举个实例或许比较容易理解一些
objc类的底层结构 method_array_t property_array_t protocol_array_t 都是继承自list_array_t
而且 这几个数据结构 都采用了一样的模板结构,不管是叫 method_list_t, property_list_t, 还是 protocol_list_t
在 list_array_tt 中 都对应了 模板List,元素都是Element
我们再分别看下 method_list_t, property_list_t 这几个模板具体定义
method_list_t
property_list_t
不管 method_list_t, property_list_t 的名字怎么起,最终都是继承自 entsize_list_tt模板结构而来, 就是模板容器List
上面的例子稍微总结下
method_array_t properties_array_t protocol_array_t 或者其他什么结构,都套用一个通用嵌套模板容器
如果你的结构复杂些,就用双层嵌套结构
而结构如果简单,就复用这个双层嵌套,当作单层List容器使用,只不过外层array只有一个元素而已
你可以试想一下ios中的分类,如果存在多个分类,均扩展同名方法,你会怎么设计呢?
再者如果设计一个哈希结构,你又会怎么设计,我们都知道哈嘻是个函数,不同的参数,得到的哈嘻位置可能会重复,你又会怎么设计这个哈嘻结构呢?
试着多想想,发散开了想,既然runtime中这么多的复用这个结构,自然这个结构很重要了,其实不只iOS底层了,其他很多语言都有这样的类似结构
c++本身就是跨平台的,而你也许听过了解c++,就必须深入了解它的模板机制
好了 回归到上面的 list_array_tt 迭代器
,在这个迭代器里,出现了 List::iterator
仔细看前面的例子,看 method_list_t, property_list_t 继承关系截图 如 method_list_t 与 <> 中的 模板名字method_list_t 是一样的
既然 method_list_t 继承自 entsize_list_tt, 那么 method_list_t中的迭代器就是 method_list_t::iterator
这是具体实例,再还原为抽象模板就是 List::iterator
如此 list_array_tt 迭代器就是调用了 entsize_list_tt中的迭代器而已
这是 list_array_tt 中的迭代器
Ptr就是模板List的指针封装而已,就是List的begin end函数,也就是 entsize_list_tt中的迭代器 begin end函数
至此 前面的关于 外层迭代器调用 内层迭代器的猜想得证
list_array_tt 中的迭代器操作理解
重载运算符++ 外层元素也就当前访问从数组中的当前元素List ,平移到下一个元素List上
然后迭代器中的m指向目标List的第一个元素,mEnd指向目标List的最后一个元素
重载运算符 *取出 当前访问的目标List 中正指向的元素 也就是m指向的元素
list_array_tt 中成员array_t 与 list理解
如果 list_array_tt 中设置了array,那么当前生效的就是 array_t结构,使用时遵循两层嵌套结构
每次访问一定需要知道 begin end,就是 先找到 array_t, 初始取到 lists(array结构中的首地址 也就是第0个元素的地址)
每次遍历 如 ++ 或 – 也就是 lists移动到 后一个List 或 前一个List,同时 m指向目标List的第一个元素 mEnd指向目标List的最后一个元素
而如果 list_array_tt 中未设置 array,那么就是单层结构
使用list这个成员 就不存在 array的目标List平移查找逻辑了
是否有双层嵌套结构 通过 arrayAndFlag & 1 来判断
双层嵌套结构数组获取 arrayAndFlag & ~1 取得
list_array_tt - attachLists流程分析
到这儿就是这篇文章最核心的内容了,但是没有前面的铺垫,这块没法阐述
为什么重要,如果要了解ios类的加载流程,这个attachLists流程你肯定绕不过去,不然你没办法理解 rwe 以及分类的加载逻辑 那这块的认知始终会处于坍缩状态
void attachLists(List* const * addedLists, uint32_t addedCount)
注意 参数 addedLists 是个模板List集合,存在多个模板List
先判断是否有双层嵌套结构
如果没有双层结构,也就是目前还没有数组,并且 addedLists中只有一个元素模板List
那就继续保持无数组状态,只把 addedLists中唯一的元素List(addedLists[0])取出,赋给list
如果没有双层结构,但addedLists中有多个元素模板List
开辟一个数组array,数组元素个数为 addedCount 或者 addedCount + 1,取决于原来是否有list
attachLists中的元素按顺序 从第0个位置开始,依次存放进 array中
如果原来list存在,就把原list放进 array最后一个位置
如果有双层嵌套结构,也就是已有数组
新开辟一个数组newArray,数组元素个数为 addedCount + 原数组array中List个数count
array中的旧元素,依次存放进 newArray中的 最后count个位置上
addedLists中的元素,依次存放进 newArray中的前 addedCount 个位置上
释放旧的array空间
ios底层核心模板结构 - list_array_tt entsize_list_tt相关推荐
- 视频教程-iOS底层原理班(下)/OC对象/关联对象/多线程/内存管理/性能优化-iOS
iOS底层原理班(下)/OC对象/关联对象/多线程/内存管理/性能优化 小码哥教育CEO,曾开发了2个iOS的流行开源框架(MJRefresh.MJExtension),目前在国内的使用率非常高. 李 ...
- iOS底层探索二(OC 中 alloc 方法 初探)
前言 相关文章: iOS底层探索一(底层探索方法) iOS底层探索三(内存对齐与calloc分析) iOS底层探索四(isa初探-联合体,位域,内存优化) iOS底层探索五(isa与类的关系) iOS ...
- iOS学习——核心动画之Layer基础
iOS学习--核心动画之Layer基础 1.CALayer是什么? CALayer我们又称它叫做层.在每个UIView内部都有一个layer这样一个属性,UIView之所以能够显示,就是因为它里面有这 ...
- iOS底层探索(二) - 写给小白看的Clang编译过程原理
iOS底层探索(一) - 从零开始认识Clang与LLVM 写在前面 编译器是属于底层知识,在日常开发中少有涉及,但在我的印象中,越接近底层是越需要编程基本功,也是越复杂的.但要想提升技术却始终绕不开 ...
- 10个最佳iOS Photo App模板
您对制作照片应用感兴趣吗? 应用模板可以使您的梦想成真. 无论您是要构建用于照片编辑的应用程序,向照片添加文本还是创建自己的社交媒体照片应用程序,这里都有一个照片应用程序模板. 出色的iOS照片应用程 ...
- iOS底层原理之架构设计
文章目录 何为架构? MVC - Apple版 MVC – 变种 MVP MVVM 设计模式 面试题 何为架构? 架构(Architecture):软件开发中的设计方案,类与类之间的关系.模块与模块之 ...
- iOS底层原理总结 - OC对象的本质
苹果官方文档 The Objective-C language defers as many decisions as it can from compile time and link time t ...
- iOS底层原理探究 第一探. 事件传递和响应者链
一. 声明: 本文意在探讨, 也参考了几位大神的文章, 在最后我会把链接发出来, 如果有理解错误的地方, 请大神们指正哈! 二. 前言: 最近自己做项目的时候, 用到了UITabbarContro ...
- iOS底层原理之内存管理
文章目录 定时器 CADisplayLink.NSTimer GCD定时器 内存管理 iOS程序的内存布局 Tagged Pointer OC对象的内存管理 拷贝 引用计数的存储 dealloc 自动 ...
最新文章
- 再见XShell!这款国产终端更好用!
- Python 基础 - Day 5 Assignment - ATM
- Linux基础命令--date
- 对比学习(Contrastive Learning)相关进展梳理
- android menu 小红点,Android自定义ActionProvider ToolBar实现Menu小红点
- python标准库sys_Python标准库之Sys模块使用详解
- 开课吧:Html5有哪些新特性?
- 完成一个简单的时间片轮转多道程序内核代码
- npm ERR! y@1.0.0 dev: `webpack-dev-server --inline --progress --config build/webpack.dev.conf.js`
- 用友NC单据模板公式
- 【Mac 教程系列第 8 篇】Mac 更换锁屏时的头像
- git常用命令(不定时更新)
- c语言fprintf 数组,C语言fprintf()函数:格式化输出到一个流中
- CMS系统简介(从简介到使用)
- 计算机图形学中点画线法
- Reflector反编译.NET文件后修复
- 四川大学计算机学院软件工程期末,四川大学软件工程期末复习ppt
- ARM Linux Qt 5.x.x 无标题栏
- Nginx代理无法访问Nexus问题
- Python报错ReadTimeoutError
热门文章
- 服务器系统我们无法创建新的分区,安装Win10系统提示“无法创建新的分区也找不到现有的分区”如何解决...
- linux c语言定时关机,linux 定时关机命令
- 抖音购物车功能开放申请,分享好物满足电商购物体验感
- linux unzip乱码,Linux 中unzip解压时中文乱码的解决办法
- 外观专利申请流程及时间及费用
- StringBuilder简介
- ifree卡黄金版和普通ifree卡的区别
- 【Java】DateUtils.truncate不应该再被使用
- 盛大圈圈 Widget 开发指南 编码要求
- layer ui ajax 样式,layerUi与AJAX的一种思路