在探索Alloc 與Init時(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 指向地址空間相同,指針地址不同

如何查看alloc方法源碼出處
通過添加斷點(diǎn)進(jìn)行查看
-
在代碼處添加斷點(diǎn)
添加斷點(diǎn).png -
按住ctrl鍵,點(diǎn)step按鈕
Step.png -
查看系統(tǒng)函數(shù)
objc_alloc
ojbc_alloc.png -
添加符號(hào)斷點(diǎn)
objc_alloc
Symbol.png -
找到對(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ù))
- 計(jì)算開辟空間的大小
cls->instanceSize,(16字節(jié)對(duì)齊) - 開辟內(nèi)存空間
calloc - 將指針與類進(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];
}




