你真的了解alloc, new,init 吗?
作为一名多年的程序员,天天在不停的的初始化对象,但是alloc底层做了什么,我们先来个demo看一下
demo代码如下:
WBJPerson *p1 = [WBJPerson alloc];
WBJPerson *p2 = [p1 init];
WBJPerson *p3 = [p1 init];
WBJPerson *objc = [WBJPerson alloc];
NSLog(@"%@——-%p——-%p",p1,p1,&p1);
NSLog(@"%@——-%p——-%p",p2,p2,&p2);
NSLog(@"%@——-%p——-%p",p3,p3,&p3);
NSLog(@"%@——-%p——-%p",objc,objc,&objc);
输出结果如下:
**<WBJPerson: 0x282515610>——-0x282515610——-0x16fb85268**
**<WBJPerson: 0x282515610>——-0x282515610——-0x16fb85260**
**<WBJPerson: 0x282515610>——-0x282515610——-0x16fb85258**
**<WBJPerson: 0x2825156a0>——-0x2825156a0——-0x16fb85250**
分析结果:
p1,p2,p3 对象的地址是一样的,但是指针的地址是不一样的。
objc和p1,p2,p3打印结果,对象的地址和指针的地址都不一样。

image
准备工作下载objc源码: objc4-818.2 如下图

image
824下载失败,我这里用的是818
M1的电脑编译通过,但是运行报错

image
报错信息:objc[53013]: task_restartable_ranges_register failed (result 0x6: (os/kern) resource shortage)
解决办法:源码搜索task_restartable_ranges_register****,干掉它。就是这么简单粗暴

image
在alloc方法打个断点:

截屏2021-06-08 下午9.48.20.png
断点没有执行,原因是main.m不在首位

截屏2021-06-08 下午10.31.47.png
下一步alloc 会调用 _objc_rootAlloc

截屏2021-06-08 下午9.51.36.png
_objc_rootAlloc 会调用callAlloc

截屏2021-06-08 下午9.52.53.png
callAlloc 会调用 _objc_rootAllocWithZone

截屏2021-06-08 下午9.54.02.png
_objc_rootAllocWithZone会调用_class_createInstanceFromZone

截屏2021-06-08 下午9.55.33.png
其中cls->instanceSize(extraBytes)方法系统做了16字节对齐。内存优化
obj->initInstanceIsa(cls, hasCxxDtor); 关联isa
最后我们画面了流程图

截屏2021-06-08 下午10.06.21.png
思维扩展
一般我们的单例这么写,根据alloc流程,防止外部alloc破坏单例。我们重写allocWithZone
+ (instancetype)sharedSingleton {
static MyManager *_sharedSingleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//不能再使用alloc方法
//因为已经重写了allocWithZone方法,所以这里要调用父类的分配空间的方法
_sharedSingleton = [[super allocWithZone:NULL] init];
});
return _sharedSingleton;
}
//重写 allocWithZone
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
return [MyManager sharedSingleton];
}
当然还有防止new,copy 方法。实际上new = [[alloc ] init]
+ (id)new {
return [callAlloc(self, false/*checkNil*/) init];
}