NSObject是OC中大部分类的基类,了解NSObject对象的初始化对于我们进一步理解对象内存的管理有一定帮助,本文主要探索alloc和init底层实现。
如何debug源码
可以参考 https://juejin.cn/post/6844903959161733133
alloc
新建一个工程,在main方法里添加代码
1 | NSObject *objc = [NSObject alloc]; |
添加一个断点符号 objc_alloc
运行工程,现在项目就会断点到objc_alloc方法
1 | objc_alloc(Class cls) |
这里会调用 callAlloc方法,参数checkNil = true,allocWithZone = false,下面具体看callAlloc方法
callAlloc方法
1 | callAlloc(Class cls, bool checkNil, bool allocWithZone=false) |
可以看出如果有自定义的allocWithZone方法就会调用_objc_rootAllocWithZone方法,后面会根据allocWithZone是否为true选择执行allocWithZone还是alloc方法。这里我们一步步走断点,最后调用的是alloc方法。
1 | + (id)alloc { |
alloc的方法调用了_objc_rootAlloc
1 | _objc_rootAlloc(Class cls) |
可以看到_objc_rootAlloc调用的也是callAlloc方法,和上一次调用不同的是参数checkNil = true allocWithZone = true
第二次调用callAlloc方法
一步步执行断点看到这次执行到allocWithZone方法
1 | + (id)allocWithZone:(struct _NSZone *)zone { |
可以看到核心代码在_class_createInstanceFromZone方法里
1 | _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, |
_class_createInstanceFromZone方法主要调用了三个函数 instanceSize、calloc、initInstanceIsa
先看instanceSize函数
1 | inline size_t instanceSize(size_t extraBytes) const { |
这个函数的返回值是一个size_t的数据,在calloc函数中会用到这个返回值。即请求开辟的内存空间大小,并且开辟的空间大小不小于16。而且调用的了alignedInstanceSize函数来进行字节对齐。即开辟的内存空间大小一定是16字节的整数倍。
calloc是C语言的函数,开辟内存空间
initInstanceIsa函数 对象isa的初始化,以及绑定内存空间
1 | objc_object::initInstanceIsa(Class cls, bool hasCxxDtor) |
init
init做的事情比较简单,直接将生成的对象返回
1 | - (id)init { |