- 从今天开始记录下自己学习的一些心得----开始的日子
oc中,万物皆可对象,对于对象初始化方式一般来说就是
[[class alloc]init]或[claas new]或者开发者自定义的一些初始化方法比如:[[class alloc]initWithFrame:()]等,关于他们的区别今天暂时不说,网上也有很多资料。今天主要想讲的alloc的流程,到底是怎么样实现的。
1.alloc&init
我们可以发现p1,p2,p3相同,说明
alloc后对象内存确定后,在进行init 的时候改变的是指向该对象的指针地址发生改变
2.三种探寻底层代码流程的方式
2.1符号断点
当法处打断点后,control + step into 进入 找到方法,添加符号断点进行分析
2.2汇编
断点打在想要知道的地方,Xcode -> Debug -> Debug Workflow -> Always Show Disassembly 进入汇编找到跳转的方法
此时有两种选择方式,你可以继续
control step into不断的进入查看流程,但是中间比较繁琐有可能。
你也可以通过上面的符号断点找到关键的方法进行分析
2.3符号断点,断住位置
我们开发中,可以根据我们探究的方法直接添加符号断点,比如alloc的探究,我们直接给alloc添加符号断点
但是值得注意的是可能会有其他类调用该方法,我们可以运行的时候跳过,走到我们关注的方法的时候在打开
3. 源码分析
我们通过下符号断点的形式看
alloc方法,由于只能看到.h文件,没办法看到.mm的具体实现,这个时候就需要我们定位objec源码。
进入后发现首先会调用alloc方法会调用_objc_rootAlloc 但是实际情况llvm会进行封装alloc 方法变为objc_alloc
之后继续跟发现
_objc_rootAlloc 会调用callAlloc
这个时候发现alloc的核心是callAlloc
发现如果是objc2 进入首先检查这个类没有的话直接返回nil;
进入
fastpath如果这个必然存在的类的指针对象有默认的 alloc/allocwithzone方法后进入_objc_rootAllocWithZone之后继续进入会调用_class_createInstanceFromZone
首先我们先要计算出这个开辟所需的空间大小
size = cls->instanceSize(extraBytes);
如果知道要分配的内存空间的大小的话,调用malloc返回一个对象,不是的话调用calloc返回的是一个数组申请开辟一个内存,返回地址指针
然后判断obj是否存在,不存在的话就返回一个badAcllocHandler或者nil
之后进行初始化isa指针对象 obj->initInstanceIsa(cls, hasCxxDtor);关联相连的类
3.init&& new
- (id)init {
return _objc_rootInit(self);
}
+ (id)new {
return [callAlloc(self, false/*checkNil*/) init];
}
init实例方法 返回一个实例化自己,方便我们转换其它类型。new就是 alloc 方法和init合并了。
整体的流程图大概如下
如有错误,请大家多多包涵。