OC对象底层探索 — alloc创建对象
2019-12-25 本文已影响0人
Dezi
用于记录iOS底层学习,以备后续回顾
OC对象底层探索
前言
- alloc:iOS开发中为对象申请开辟内存的方法。
学习文档
配置环境+资料:
objc4-756.2源码 + Xcode11 + MacOS 10.15
官方源码下载地址
iOS_objc4-756.2 最新源码编译调试
一、探索alloc所在源码的三个方法
- Control + Step into:objc_alloc
- Symbolic Breakpoint 符号断点:libobjc.A.dylib`+[NSObject alloc]
- 菜单Debug -> Debug Workflow -> Always show Disassembly 查看汇编代码
二、开始入坑
1、加断点探索源码在libobjc.A.dylib中
image.png
2、运行源码调试
- 第一步
+ (id)alloc {
return _objc_rootAlloc(self);
}
- 第二步
id
_objc_rootAlloc(Class cls)
{
return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
- 第三步
// Call [cls alloc] or [cls allocWithZone:nil], with appropriate
// shortcutting optimizations.
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
if (slowpath(checkNil && !cls)) return nil;
#if __OBJC2__
if (fastpath(!cls->ISA()->hasCustomAWZ())) {
// No alloc/allocWithZone implementation. Go straight to the allocator.
// fixme store hasCustomAWZ in the non-meta class and
// add it to canAllocFast's summary
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 {
// Has ctor or raw isa or something. Use the slower path.
id obj = class_createInstance(cls, 0);
if (slowpath(!obj)) return callBadAllocHandler(cls);
return obj;
}
}
#endif
// No shortcuts available.
if (allocWithZone) return [cls allocWithZone:nil];
return [cls alloc];
}
主要对第三步进行详细流程分析,见流程图
注:
8字节对齐:以空间换取时间,下一篇主要研究字节对齐
init、new探索
init:探索源码,仅仅是返回self,无实质作用,so仅仅是为了规范代码,提供接口层,工厂设计模式方便重写、自定义
- (id)init {
return _objc_rootInit(self);
}
id
_objc_rootInit(id obj)
{
// In practice, it will be hard to rely on this function.
// Many classes do not properly chain -init calls.
return obj;
}
new:探索源码 new = alloc + init
+ (id)new {
return [callAlloc(self, false/*checkNil*/) init];
}