alloc 流程分析

一、分析之前

  1. alloc 到底做了什么事?
  2. init 有什么用?
  3. [[Class alloc] init] 与 new有什么区别?

alloc 到底做了什么事

先看一个例子

1.png

Why? Person1、2、3打印的地址竟然是一模一样
从反向证明是alloc方法开辟了内存,此时我想看看alloc到底做了什么,结果:
+ (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
点不进去了,难道就这么算了?

二、alloc源码分析

准备工作

1.从 苹果官方开源代码列表 找到 objc4源码,下载好后打开如下:

2.png

2.搜索定位alloc方法:

+ (id)alloc {
    return _objc_rootAlloc(self);
}

3.跟踪代码,流程如下:


3.jpg

4.一眼看去也不知道干啥的函数一通调用,最终好像都有两个关键字:calloc、initIsa
5.那么calloc、initIsa到底在干什么?断点看看情况:


5.png

可以看到调用:

obj = (id)calloc(1, size);

就开辟了一个空间,但是只有一个内存地址
调用

obj->initInstanceIsa(cls, hasCxxDtor);

刚刚开辟的地址就有了类型

  1. 因此,我们就可以确定alloc至少做了两件事:开辟内存、初始化isa指针并关联类

既然alloc将开辟内存关联类型都做了,那么init又是在干嘛呢?

  1. 定位代码:
- (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;
}
  1. 可见init仅仅只是将alloc开辟的对象直接返回了,是一种工厂化的设计,方便我们对类进行重写。

那么new 与[[Class alloc] init] 有什么区别呢?

  1. 定位代码
+ (id)new {
    return [callAlloc(self, false/*checkNil*/) init];
}

id _objc_rootAlloc(Class cls)
{
    return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}

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];
}
  1. 可见new和[[Class alloc] init],唯一区别就是allocWithZone参数为false

你可能感兴趣的:(alloc 流程分析)