iOS底层原理

alloc在底层干了什么?init又干了什么?new又干了什么?

2020-09-06  本文已影响0人  何必太轻浮

我们最常用的创建对象方法一般是

MCPerson *objc1 = [[MCPerson alloc]init];
//or
MCPerson *objc2 = [MCPerson new];

这两个创建方法有什么区别呢,我们先针对第一个alloc,init创建对象的流程进行分析

如图我们发现,对象在alloc的时候已经被创建出来了,于是我们先重点看看alloc主要干了什么。

于是,在上图第15行打下断点,重新运行


pic2

断点断住这里(objc_alloc)


pic3

往下走,到了定义objc_alloc的地方,调用了callAlloc方法


pic4

继续往下走,到了callAlloc定义的地方,这个地方会调用两次,第一次走objc_msgSend方法,第二次走_objc_rootAllocWithZone方法


pic5

继续往下走,到了class_createInstanceFromZone方法,这就是大致alloc方法的调用流程了


pic5

class_createInstanceFromZone 这个方法比较重要,里面包含 计算对象大小,申请内存(16字节对齐),绑定类这几个操作

_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
                              int construct_flags = OBJECT_CONSTRUCT_NONE,
                              bool cxxConstruct = true,
                              size_t *outAllocatedSize = nil)
{
    ASSERT(cls->isRealized());

    // Read class's info bits all at once for performance
    bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor();
    bool hasCxxDtor = cls->hasCxxDtor();
    bool fast = cls->canAllocNonpointer();
    size_t size;
    // 1:要开辟多少内存
    size = cls->instanceSize(extraBytes);
    if (outAllocatedSize) *outAllocatedSize = size;

    id obj;
    if (zone) {
        obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
    } else {
        // 2;怎么去申请内存
        obj = (id)calloc(1, size);
    }
    if (slowpath(!obj)) {
        if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
            return _objc_callBadAllocHandler(cls);
        }
        return nil;
    }

    // 3: 绑定类
    if (!zone && fast) {
        obj->initInstanceIsa(cls, hasCxxDtor);
    } else {
        // Use raw pointer isa on the assumption that they might be
        // doing something weird with the zone or RR.
        obj->initIsa(cls);
    }

    if (fastpath(!hasCxxCtor)) {
        return obj;
    }

    construct_flags |= OBJECT_CONSTRUCT_FREE_ONFAILURE;
    return object_cxxConstructFromClass(obj, cls, construct_flags);
}

alloc流程绘制成流程图


pic6

简单来说,alloc方法调用完后,对象已经创建了

在这里思考一个问题,在底层调用init方法,是调用NSObject的init方法还是子类重写的?

pic9 pic9 pic10

发现,其实new方法也是会遵循方法查找原则的,so,alloc、init、new方法简单的分析就到这里了,有兴趣的小伙伴可以关注我哦,我会继续更新的哦。

objc源码下载地址:
https://opensource.apple.com/tarballs/
https://opensource.apple.com

上一篇 下一篇

猜你喜欢

热点阅读