1.准备工作
源码下载:objc4-781 源码编译:可参考教程 源码编译调试
2.源码分析
2.1 alloc源码
源码在手,天下我有!接着就很简单了,创建一个Person类,然后调用 alloc 方法,main.m 如下:
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
Person *objc = [Person alloc];
NSLog(@"Hello, World! %@", objc);
}
return 0;
}
此时,按住command 鼠标左键就可以跳入alloc方法内部了 【第一步】NSObject.mm中的 alloc 实现,可以看到alloc内部调用了一个叫 _objc_rootAlloc 的函数,并传入了当前Person类
+ (id)alloc {
return _objc_rootAlloc(self);
}
【第二步】_objc_rootAlloc内部又调用了 callAlloc() ,同样传入了Person类
id _objc_rootAlloc(Class cls)
{
return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
【第三步】callAlloc函数内部
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() ? 我们的 NSObject 类经历过改版,原本会调用allocWithZone:方法,改版后去掉了。 【第四步】