概述
我們在這樣alloc
一個對象時oc
底層究竟做了啥 QHPerson *p = [QHPerson alloc] ;
要想分析我們必須先拿到objc的源碼佑钾,當然也有其他的方式坏瞄,比如符號斷點、匯編等逗抑,但是源碼分析最直接。
蘋果源碼官網,下載后可以編譯一下objc源碼荒辕,這里不講述如何編譯
oc alloc 流程圖
先來一份總結的oc alloc流程圖
alloc 流程圖.png
源碼分析
第一步:NSObject 里面會調用
+ (id)alloc {
return _objc_rootAlloc(self);
}
第二步:這里有一個objc
版本的判斷总寻,但是不影響主流程
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));
}
第三步:創(chuàng)建實例
...
//計算實例要分配的內存大小器罐,里面有一個算法,oc對象最少時16字節(jié)渐行,8的倍數(shù)轰坊。也就是16 、24祟印、32 ...
size = cls->instanceSize(extraBytes);
if (outAllocatedSize) *outAllocatedSize = size;
//調用c語音calloc開辟空間
id obj;
if (zone) {
obj = (id)malloc_zone_calloc((malloc_zone_t *)zone, 1, size);
} else {
obj = (id)calloc(1, size);
}
//實例對象關聯(lián)類
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);
}