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 { |