了解alloc、Init 以及new方法

在探索AllocInit時(shí),先輸出兩個(gè)對(duì)象的地址以及指向?qū)ο笾羔樀牡刂?,查看有什么區(qū)別。下面是一段Objective-C的代碼

  UIView  *p1 = [UIView alloc];
  UIView  *p2 = [UIView alloc];
  UIView  *p3 = [p1 init];
  UIView  *p4 = [p2 init];
  UIView  *p5 = [p2 init];
  NSLog(@"對(duì)象p1%@ - 指針地址%p",p1,&p1);
  NSLog(@"對(duì)象p2%@ - 指針地址%p",p2,&p2);
  NSLog(@"對(duì)象p3%@ - 指針地址%p",p3,&p3);
  NSLog(@"對(duì)象p4%@ - 指針地址%p",p4,&p4);
  NSLog(@"對(duì)象p5%@ - 指針地址%p",p5,&p5);

得到結(jié)果,可知P1 與 P3 指向地址空間相同, 指針地址不同;P2 與 P4、P5 指向地址空間相同,指針地址不同


截屏2020-09-06 下午2.46.50.png
如何查看alloc方法源碼出處
通過添加斷點(diǎn)進(jìn)行查看
  1. 在代碼處添加斷點(diǎn)


    添加斷點(diǎn).png
  2. 按住ctrl鍵,點(diǎn)step按鈕


    Step.png
  3. 查看系統(tǒng)函數(shù)objc_alloc

    ojbc_alloc.png

  4. 添加符號(hào)斷點(diǎn)objc_alloc

    Symbol.png

  5. 找到對(duì)應(yīng)庫


    libobjc.A.dylib.png
alloc的流程

通過在objc源碼 找到NSObject.mm中我們找到alloc方法的實(shí)現(xiàn)。

alloc

alloc類方法下,執(zhí)行_objc_rootAlloc函數(shù)。

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

_objc_rootAlloc函數(shù)內(nèi),執(zhí)行callAlloc函數(shù)

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

通過符號(hào)斷點(diǎn)調(diào)試,發(fā)現(xiàn)在callAlloc函數(shù)下執(zhí)行objc-runtime-new.mm文件下的_objc_rootAllocWithZone函數(shù)。

static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
    if (slowpath(checkNil && !cls)) return nil;
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        return _objc_rootAllocWithZone(cls, nil);
    }
#endif

    // No shortcuts available.
    if (allocWithZone) {
        return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
    }
    return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}


_objc_rootAllocWithZone

_objc_rootAllocWithZone ,執(zhí)行_class_createInstanceFromZone函數(shù)

id
_objc_rootAllocWithZone(Class cls, malloc_zone_t *zone __unused)
{
    // allocWithZone under __OBJC2__ ignores the zone parameter
    return _class_createInstanceFromZone(cls, 0, nil,
                                         OBJECT_CONSTRUCT_CALL_BADALLOC);
}
_class_createInstanceFromZone(核心函數(shù))
  1. 計(jì)算開辟空間的大小cls->instanceSize,(16字節(jié)對(duì)齊)
  2. 開辟內(nèi)存空間calloc
  3. 將指針與類進(jìn)行綁定obj->initInstanceIsa
static ALWAYS_INLINE id
_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;
    size = cls->instanceSize(extraBytes);
    if (outAllocatedSize) *outAllocatedSize = size;

    id obj;
    if (zone) {
        obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
    } else {
        obj = (id)calloc(1, size);
    }
    if (slowpath(!obj)) {
        if (construct_flags & OBJECT_CONSTRUCT_CALL_BADALLOC) {
            return _objc_callBadAllocHandler(cls);
        }
        return nil;
    }
    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);
}
Init

Init方法

- (id)init {
    return _objc_rootInit(self);
}

_objc_rootInit函數(shù)

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;
}

通過查看源碼,我們可以發(fā)現(xiàn)init返回的是它本身。

new

new函數(shù)中直接調(diào)用了callAlloc函數(shù),且調(diào)用了init函數(shù),所以可以得出new 其實(shí)就等價(jià)于 [alloc init]的結(jié)論。

+ (id)new {
    return [callAlloc(self, false/*checkNil*/) init];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容