一、alloc、init、new源码笔记

本文由快学吧个人写作,以任何形式转载请表明原文出处。

一、需要的资料

objc4-876,地址 : github.com/apple-oss-d...

二、探索的思路

1、要探索alloc和init和new具体做了什么,就需要知道什么时候我们用alloc和new,这个很容易,OC中一个对象的初始化最常用的就是 [[Obj alloc] init]和[Obj new],所以,第一步我们需要一个类,并且初始化一个对象。

2、要看alloc、init和new分别做了什么,就需要把它们分开来看。

3、我们最常用也是最基本最常见的类就是NSObject,我们创建的一些基本的类大多都继承于它,所以我们以NSObject的alloc、init和new方法来探索。

3、找到NSObject的源码,进行探索。

三、需要的基本知识储备

字节对齐 :

1、为什么要字节对齐

因为苹果官方要求的。

2、为什么要这么要求

不止是苹果官方,几乎所有的语言,都会要求内存对齐。

如下图 :

首先,我们存储数据的目的不是单纯的存储,而是要在需要的时候可以调用,而cpu是不是以字节为单位来读取数据的,而是以"块"为单位。

如果所有申请内存空间的数据都要这样去申请,并且拿到不同大小的内存空间去使用。

那么在我们再调用这些数据的时候,cpu要不断的变换读取数据的内存长度大小,来精准的获取数据,这是很浪费资源的行为。

所以,字节对齐,实际上是一种以空间换取时间的方式,让cpu更高效的读取内存中的数据。

3、iOS的字节对齐

iOS的字节对齐是以16字节为基本数,开辟内存空间的大小需要是16的整数倍。

为什么iOS要以16字节进行字节对齐?

因为OC对象中,第一位一定有一个isa指针,而isa指针的大小就是8字节,如果仅仅以8字节进行字节对齐,如果两个对象都是没有其他任何属性的对象(仅仅有isa指针),那么这两个对象的内存空间就会挨在一起,就容易造成数据的混乱。

iOS也有对8字节对齐的要求,具体的详情在下面的苹果官方字节对齐算法代码那里有解释。

4、苹果官方的字节对齐算法

c 复制代码
static inline size_t align16(size_t x) {
    return (x + size_t(15)) & ~size_t(15);
}

四、alloc

1、alloc方法的跳转

1、打开准备的资料 : objc4-876的文件。

2、在Xcode的Navigators搜索alloc {,因为方法的实现都是以 { 来开始的,所以带上 { 可以省略很多麻烦。

3、在NSObject.mm文件找到 alloc的实现方法。.mm格式文件是为了支持C++和OC的混编。

4、进入_objc_rootAlloc方法。

5、进入callAlloc方法。

到这里我们可以发现,alloc的实现方法,一定是在callAlloc中提到的_objc_rootAllocWithZone或者allocWithZone方法。

如果可以断点调试的话,可以发现,实际上JDPersonalloc方法进入的是第二个if,也就是fastpath的判断里面,进入了_objc_rootAllocWithZone方法。

2、alloc的核心实现

1、在搜索栏搜索_objc_rootAllocWithZone(找到方法的实现。

2、进入_class_createInstanceFromZone方法。

这里保留一下传入的参数,以便探索。这里可以进入一下OBJECT_CONSTRUCT_CALL_BADALLOC,这个参数看一下,发现是一个枚举值,是2。所以传入的参数就是(cls, 0, nil, 2)。

3、_class_createInstanceFromZone方法的实现

3、alloc申请内存中的一些细节

1、如何计算申请内存的对象所需内存空间的大小?

这一步在_class_createInstanceFromZone方法中进行了实现,看上图中的

ini 复制代码
size = cls->instanceSize(extraBytes);

这里的size就是所需内存空间的大小,计算所用到的方法是instanceSize。直接进入instanceSize方法。

2、计算内存大小

重点在fastInstanceSizealignedInstanceSize

fastInstanceSize重点在align16 :

alignedInstanceSize重点在word_align :

3、align16word_align的源码

就是字节对齐的算法代码。

这里有一点,两个字节对齐的算法,一个是8字节对齐,一个是16字节对齐。

原因是8字节对齐的受众是对象内部的属性,对象内部的属性需要遵循8字节对齐的原则,而16字节对齐的受众则是对象。

比如 : obj1和obj2之间需要满足16字节对齐,而obj1的内部属性attr1和attr2需要满足8字节对齐。

五、init

和alloc同样,在objc4-876源码中找init的实现,在Xcode的Navigators搜索init {,找到NSObject.mm文件中的init实现。

类方法直接返回self,没有做任何的操作。实例方法调用_objc_rootInit,看一下 :

一样直接返回self。

其实init的意义在官方的注释中已经表达清楚了,init就是工厂模式,为了给开发者在实际的应用中提供一个自己可以自定义的接口。

六、new

源码查找方法同上。

new直接调用了callAlloc方法,和alloc的区别就是alloc调用的是_objc_rootAlloc方法,然后又_objc_rootAlloc调用的callAlloc,再就是传递的最后一个形参不一样。
new会直接调用init方法,如果我们自己定义一些init的方法,类似于initWith之类的,new只会调用init,而不会调用我们的init方法,所以用的比较少。

七、总结

1、alloc申请内存,字节对齐,绑定isa,核心方法是callAlloc(实际入口),instanceSize(计算开辟内存的大小),calloc(申请内存,返回地址指针),initIsa(绑定isa)。

2、init提供重写的机会,给开发者根据自身情况做自定义。

3、new直接调用了alloc的实际入口callAlloc方法,然后调用了init方法。不会调用我们自定义的一些类似于initWith的方法。

相关推荐
2501_915918411 小时前
Web 前端可视化开发工具对比 低代码平台、可视化搭建工具、前端可视化编辑器与在线可视化开发环境的实战分析
前端·低代码·ios·小程序·uni-app·编辑器·iphone
2501_915106322 小时前
iOS 使用记录和能耗监控实战,如何查看电池电量消耗、App 使用时长与性能数据(uni-app 开发调试必备指南)
android·ios·小程序·uni-app·cocoa·iphone·webview
凉白开<--2 小时前
mardown-it 有序列表ios序号溢出解决办法
ios·vue
Digitally3 小时前
如何将 iPhone 备份到电脑/PC 的前 5 种方法
ios·电脑·iphone
Swift社区5 小时前
在企业内部分发 iOS App 时如何生成并使用 manifest.plist
macos·ios·cocoa
他们都不看好你,偏偏你最不争气8 小时前
【iOS】push 和 present
ios
2501_9160137411 小时前
HTTPS 抓包难点分析,从端口到工具的实战应对
网络协议·http·ios·小程序·https·uni-app·iphone
2501_9159184113 小时前
uni-app 项目 iOS 上架效率优化 从工具选择到流程改进的实战经验
android·ios·小程序·uni-app·cocoa·iphone·webview
00后程序员张13 小时前
如何在不同 iOS 设备上测试和上架 uni-app 应用 实战全流程解析
android·ios·小程序·https·uni-app·iphone·webview
wjm04100614 小时前
ios面试八股文
ios·面试