NSObject +alloc做了什么
2020/3/10 23:01:36
本文主要是介绍NSObject +alloc做了什么,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
窥探
通过下符号断点的方式来跟踪 [NSObject alloc]
//下了两个符号断点 1、objc_alloc 2、+[NSObject alloc] //结果是 1 2 复制代码
经过编译器一顿操作,似乎结合和预想不是完全吻合
在使用+[NSObject alloc]
的时候实际上调用的是libonjc.A.dylib objc_alloc
,并不是预想的libonjc.A.dylib objc_msgSend
,这里看一llvm
的源码,对alloc
做了处理(第一次调用objc_alloc
,第二次调用+alloc
)
梳理
1. 从objc_alloc开始
// Calls [cls alloc]. id objc_alloc(Class cls) { return callAlloc(cls, true/*checkNil*/, false/*allocWithZone*/); } 复制代码
- 这里就做一件事情设置两个参数
checkNil = true
、allocWithZone = false
- 初次调用
callAlloc
需要检查nil
,而且不使用zone
2. callAlloc
static id callAlloc(Class cls, bool checkNil, bool allocWithZone=false) { if (slowpath(checkNil && !cls)) return nil; #if __OBJC2__ //是否实现 allocWithZone if (fastpath(!cls->ISA()->hasCustomAWZ())) { //未实现allocWithZone // canAllocFast直接返回了false,直接看else if (fastpath(cls->canAllocFast())) { // No ctors, raw isa, etc. Go straight to the metal. bool dtor = cls->hasCxxDtor(); id obj = (id)calloc(1, cls->bits.fastInstanceSize()); if (slowpath(!obj)) return callBadAllocHandler(cls); obj->initInstanceIsa(cls, dtor); return obj; } else { // 核心 创建实例 id obj = class_createInstance(cls, 0); if (slowpath(!obj)) return callBadAllocHandler(cls); return obj; } } #endif // No shortcuts available. if (allocWithZone) return [cls allocWithZone:nil]; //+alloc 终于轮到你了 return [cls alloc]; } 复制代码
hasCustomAWZ()
是检查是否实现了+allocWithZone
- 没有实现
+allocWithZone
就通过class_createInstance(cls, 0)
来创建实例 - 实现了
+allocWithZone
,但还需要allocWithZone == true
才会调用,首次调用一定不会触发在objc_alloc
中传了false
return [cls alloc];
最后这段代码才是主流程
3. class_createInstance
class_createInstance(Class cls, size_t extraBytes) { //调用了 私有方法 _class_createInstanceFromZone return _class_createInstanceFromZone(cls, extraBytes, nil); } id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, bool cxxConstruct = true, size_t *outAllocatedSize = nil) { if (!cls) return nil; assert(cls->isRealized()); // Read class's info bits all at once for performance bool hasCxxCtor = cls->hasCxxCtor(); //有c++构造函数 bool hasCxxDtor = cls->hasCxxDtor(); //有c++析构函数 bool fast = cls->canAllocNonpointer(); //快速创建,是否允许非纯指针,也就是isa的优化 //计算实例大小 size_t size = cls->instanceSize(extraBytes); if (outAllocatedSize) *outAllocatedSize = size; id obj; if (!zone && fast) { //不使用zone并且支持isa优化的对象分配空间 obj = (id)calloc(1, size); if (!obj) return nil; //对象实例初始化isa obj->initInstanceIsa(cls, hasCxxDtor); } else { if (zone) { //使用zone 分配空间 obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size); } else { //不使用 zone分配空间 obj = (id)calloc(1, size); } if (!obj) return nil; //纯指针的初始化 obj->initIsa(cls); } if (cxxConstruct && hasCxxCtor) { obj = _objc_constructOrFree(obj, cls); } return obj; } 复制代码
3. instanceSize
//拿到类对象的 ro 对象的原始大小 uint32_t unalignedInstanceSize() { assert(isRealized()); return data()->ro->instanceSize; } /* 字节对齐: 为了让CPU 寻址更简单快速,用空间换时间 */ uint32_t alignedInstanceSize() { return word_align(unalignedInstanceSize()); } //计算对象大小 size_t instanceSize(size_t extraBytes) { size_t size = alignedInstanceSize() + extraBytes; // CF requires all objects be at least 16 bytes. //最小 16个字节 if (size < 16) size = 16; return size; } 复制代码
关于字节对齐的内容
####4. InitIsa
inline void objc_object::initIsa(Class cls) { //纯指针的初始化 isa 方法 initIsa(cls, false, false); } inline void objc_object::initInstanceIsa(Class cls, bool hasCxxDtor) { //非纯指针的初始化 isa 方法 initIsa(cls, true, hasCxxDtor); } /* 初始化Isa 参数: cls 类对象 nonpointer 是否是非指针,就是经过优化的isa hasCxxDtor 是否存在c++析构 */ inline void objc_object::initIsa(Class cls, bool nonpointer, bool hasCxxDtor) { assert(!isTaggedPointer()); // if (!nonpointer) { isa.cls = cls; } else { isa_t newisa(0); newisa.bits = ISA_MAGIC_VALUE; // isa.magic is part of ISA_MAGIC_VALUE // isa.nonpointer is part of ISA_MAGIC_VALUE newisa.has_cxx_dtor = hasCxxDtor; newisa.shiftcls = (uintptr_t)cls >> 3; isa = newisa; } } 复制代码
5. +alloc
+ (id)alloc { return _objc_rootAlloc(self); } id _objc_rootAlloc(Class cls) { return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/); } 复制代码
- 未实现
+allocWithZone
将会调用+ alloc
,然后再次调用callAlloc
,这次参数不一样了不需要检查是否为空,使用zone
总结
- 控制调用
callAlloc
参数来控制执行路径,从而实现不同情况下创建对象 - 对纯指针和非纯指针的初始化
- 内存直接对齐
附上alloc分析图
这篇关于NSObject +alloc做了什么的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2022-10-05Swift语法学习--基于协议进行网络请求
- 2022-08-17Apple开发_Swift语言地标注释
- 2022-07-24Swift 初见
- 2022-05-22SwiftUI App 支持多语种 All In One
- 2022-05-10SwiftUI 组件参数简写 All In One
- 2022-04-14SwiftUI 学习笔记
- 2022-02-23Swift 文件夹和文件操作
- 2022-02-17Swift中使用KVO
- 2022-02-08Swift 汇编 String array
- 2022-01-30SwiftUI3.0页面反向传值