我们最常用的创建对象方法一般是
MCPerson *objc1 = [[MCPerson alloc]init];
//or
MCPerson *objc2 = [MCPerson new];
这两个创建方法有什么区别呢,我们先针对第一个alloc,init创建对象的流程进行分析
-
alloc到底干了什么?
如图我们发现,对象在alloc的时候已经被创建出来了,于是我们先重点看看alloc主要干了什么。
于是,在上图第15行打下断点,重新运行
断点断住这里(objc_alloc)
往下走,到了定义objc_alloc的地方,调用了callAlloc方法
继续往下走,到了callAlloc定义的地方,这个地方会调用两次,第一次走objc_msgSend方法,第二次走_objc_rootAllocWithZone方法
继续往下走,到了class_createInstanceFromZone方法,这就是大致alloc方法的调用流程了
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流程绘制成流程图
简单来说,alloc方法调用完后,对象已经创建了
-
init方法干了什么呢?
点击init方法,直接查看源码,发现啥都没做,只是返回了init方法,所以init只是一个简单的工厂设计模式,主要是方便我们重写这个方法
-
new方法干了什么呢?
new方法进入源码,发现,其实new方法就是在底层同时调用了alloc和init方法
在这里思考一个问题,在底层调用init方法,是调用NSObject的init方法还是子类重写的?
- 我在子类重写了init方法,使用new初始化对象
发现,其实new方法也是会遵循方法查找原则的,so,alloc、init、new方法简单的分析就到这里了,有兴趣的小伙伴可以关注我哦,我会继续更新的哦。
objc源码下载地址:
https://opensource.apple.com/tarballs/
https://opensource.apple.com