objc源码解读-对象生命周期

在Objective-C中,当我们创建一个对象,并调用对应的方法的时候这个对象的生命周期是如何的,方法是如何调用的,我们应该有一个最基本的认识, 假定我们有一个自定义类,CustomClass,继承自NSObject:

@interface CustomClass : NSObject

- (void)doSomething;
复制代码

当我们调用

CustomClass *customObj = [[CustomClass alloc] init];
[customObj doSomething];
复制代码

runtime到底在背后做了什么?是如何管理引用计数的?又是如何调用调用方法的。这就需要我们对objc源码进行刨根问底了。

首先我们看看,CustomClass发送alloc消息,

//1.首先调用_objc_rootAlloc,参数为CustomClass
+ (id)alloc {
return _objc_rootAlloc(self);
}

//2.再调用callAlloc
cls:CustomClass
checkNil:是否检查Cls
allocWithZone:是否分配到指定空间,默认为false,内部会对其进行优化
id _objc_rootAlloc(Class cls)
{
return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);
}
复制代码
//3.callAlloc内部实现
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
//fastpath和slowpath是编译器对判断条件做预知的优化
比如checkNil && !cls 这个条件极大多数情况都为false
这时候提前调用slowpath提高代码的效率,反之则会调用fastpath
if (slowpath(checkNil && !cls)) return nil;

//在__OBJC2__中,
#if __OBJC2__
//多数情况下Class内部都不会重写allocWithZone所以这里会使用fastpath
if (fastpath(!cls->ISA()->hasCustomAWZ())) {
// No alloc/allocWithZone implementation. Go straight to the allocator.
// fixme store hasCustomAWZ in the non-meta class and
// add it to canAllocFast's summary
if (fastpath(cls->canAllocFast())) {
// No ctors, raw isa, etc. Go straight to the metal.
// 假如能快速分配,并且有c++析构函数
bool dtor = cls->hasCxxDtor();
id obj = (id)calloc(1, cls->bits.fastInstanceSize());
if (slowpath(!obj)) return callBadAllocHandler(cls);
// 创建对象,初始化isa指针
obj->initInstanceIsa(cls, dtor);
return obj;
}
else {
// Has ctor or raw isa or something. Use the slower path.
//假如没有c++析构函数,传入class和extraBytes:0
id obj = class_createInstance(cls, 0);
if (slowpath(!obj)) return callBadAllocHandler(cls);
return obj;
}
//无论是否能快速创建,都会调用initIsa进行isa指针的初始化
}
#endif

// No shortcuts available.
if (allocWithZone) return [cls allocWithZone:nil];
return [cls alloc];
}
复制代码

生成对象customObj后调用init

//最终会调用这个函数,直接返回obj
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;
}
复制代码

Retain:

//最终都会调用这个方法,首先判断是否是nonpointer,假如是,就不会调用retain
//nonpointer指针的值不再是地址了,而是真正的值,并且因为没有isa,因此不是真正的对象
id
objc_object::sidetable_retain()
{
#if SUPPORT_NONPOINTER_ISA
assert(!isa.nonpointer);
#endif
从SideTables中获得对对应table的引用避免开辟新的内存空间
SideTable& table = SideTables()[this];

table.lock();
//获取table中对应的引用计数避免开辟新的内存空间
size_t& refcntStorage = table.refcnts[this];
//假如引用计数没有溢出
if (! (refcntStorage & SIDE_TABLE_RC_PINNED)) {
//引用计算refcntStorage左移一位
refcntStorage += SIDE_TABLE_RC_ONE;
}
table.unlock();
return (id)this;
}
复制代码

Release

uintptr_t
objc_object::sidetable_release(bool performDealloc)
{
#if SUPPORT_NONPOINTER_ISA
assert(!isa.nonpointer);
#endif
SideTable& table = SideTables()[this];

bool do_dealloc = false;

table.lock();
RefcountMap::iterator it = table.refcnts.find(this);
//没有找到引出计数
if (it == table.refcnts.end()) {
do_dealloc = true;
table.refcnts[this] = SIDE_TABLE_DEALLOCATING;
} else if (it->second < SIDE_TABLE_DEALLOCATING) {
//可能设置了弱引用
// SIDE_TABLE_WEAKLY_REFERENCED may be set. Don't change it.
do_dealloc = true;
it->second |= SIDE_TABLE_DEALLOCATING;
} else if (! (it->second & SIDE_TABLE_RC_PINNED)) {
//假如取得的value没有溢出,右移一位
it->second -= SIDE_TABLE_RC_ONE;
}
table.unlock();
if (do_dealloc  &&  performDealloc) {
((void(*)(objc_object *, SEL))objc_msgSend)(this, SEL_dealloc);
}
return do_dealloc;
}
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值