前言
所有的学习都不是死板的, 学习OC的底层原理最主要的是学习设计框架和思维, 一些比较核心地点的实现, 是一种认知的扩展, 在遇到类似的问题的时候我们可以模仿出更加高效, 易用的框架. 站在巨人的肩膀上成长.
新建项目进行探索
新建一个项目, 看一下项目的整个流程:

如上图所示: 整个项目的链接由dyld开始,
- 通过dyld的dyld_start入口, 进行整个项目的运行. 比如动态库, 共享内存, 一系列的初始化和注册回调函数全部都在这里完成.
2.libSystem_initializer系统库初始化
3.libdispatch_init GCD环境初始化
4._objc_init runtime加载, load方法等入口.
目前我们准备探索的alloc, 源码就在objc的源码中. 苹果官方文档地址
alloc和init到底做了什么

如上图所示, obj1, obj2, obj3指向的都是位于堆区的同一个Person的对象地址.
obj1,2,3本身的指针地址是位于栈区的连续地址.
从这里也可以看出, 栈区分配内存是从高往低连续分配.
alloc创建出来的对象在堆区, obj1是一个指向堆区的栈区指针
从这里看init好像什么都没有做, 当我们command点击进入alloc方法之后, 会走到NSObject.h的头文件, 找不到真实的实现了.
调试手段
在遇到很多问题的时候, 如何入手是最大的问题, 比如我们在开发中学习或者使用一个东西, 第一时间肯定是找到对应的官方文档进行了解和学习, 在对其中具体的使用模块进行深入的学习.
- 解决问题的第一步就是如何入手, 所以根据不同的方式进行调试是非常重要的
01---符号断点

在上面我添加一个objc_alloc的符号断点, 接下来就进入到了

在这里我看到_objc_rootAllocWithZone, 然后我就可以对_objc_rootAllocWithZone继续往添加符号断点进行下一步的查询
汇编查看
设置debug

在断点的地方就可以看到, symbol stub for:xxx, 后面就是对应的符号, 在符号出打断点, 然后直接根据图中的提示点击:

就进入到要找的方法内部了, 可以一次往下就走就可以了. 我这里使用的是模拟器, 对armv7, arm64, x86指令集, 对哪个熟悉就用选择不同的机器进行编译会让自己看起来更方便一遍.

直接根据alloc方法, 打上符号断点, 然后根据内部跳转的地方, 调用的符号继续进行一步一步的深入.


此外lldb, 一些第三方工具都可以用于调试处理, 怎么入手处理问题才是最关键的一步.
在断点处, 看第一行就能看到对应的类和方法都出自于哪个库. 正常情况下, 先打出汇编的debug, 然后根据方法的调用和跳转, 在使用符号断点进行深入处理更为方便.
objc源码调试
从上面我们已知alloc方法在, libobjc库中, 在苹果官方链接中找到看一看有没有对应的库, 在进行相关的查询.
github上cooci的可编译的源码, 方便大家追踪. objc4
如果我们处理的问题没有源码, 就要根据堆栈进行一步一步调试查看, 看看到底是哪个地方调用了那些方法, 产生了问题, 大量的耗时等.
alloc流程图
下图所示:

整个流程都在图里, 说几种调试方式: Debug->View Memory 然后把断点图中的地址输入View Memory的address, 就可以看到内存:


然后继续加入bool类型, float类型:


从图12可以看出, 布尔类型和int类型的合并在一个8字节的内存里了, 每人4个字节32位, 进行分配, 优化了内存.
float类型不能直接po查看, 需要其他的指令. 需要的话可以, help po, help e去查看对应的命令进行查看.
lldb的官网都可以看看, 不懂英文的谷歌直接翻译中文, 东西太庞大需要自己选择学习哪些, 一定要会挑.
总结
总体来说 ,不管学习什么内容, 第一步的学习就是模仿, 模仿好的框架, 好的内容, 把学习的对象搞懂, 第二步就是在不断的编写敲打中深入理解模仿的事物的机制, 第三步就是能有自己的设计和思维融合自己的方式进行应用和创新.
所以, 自己脑子里有了这整个的大局观, 对整个机制有了一定的认识, 即使我们写不出比这更好更优秀的作品, 当我们遇到一些问题或者需要做类似的事情的时候, 我们可以照搬过来进行修改也是要比绝大部分一般的框架要好的. 尤其是一些知名的开源第三方框架, 真的有必要好好看看, 将来一定读的到.
学习是一种习惯, 努力与时代为伍.