銷毀的開端
調(diào)用-release想鹰,release會調(diào)用:
uintptr_t objc_object::sidetable_release(bool performDealloc)
sidetable_release():
以下都是邏輯代碼坞笙,完整代碼得實現(xiàn)可以查看runtime源碼
加鎖
獲取當(dāng)前對象所在的sidetable(一個hash表),在sidetable.refcnts(RefcountMap,一個map)中查到當(dāng)前對象的迭代器
創(chuàng)建變量bool do_dealloc = false;代表是否需要dealloc
接著判斷迭代器是否是指向了sidetable的end
如果是就代表找不到:
sidetable.refcnts[this] = SIDE_TABLE_DEALLOCATING(即計數(shù)變?yōu)?)
do_dealloc = true
else if(迭代器->second(對象的計數(shù)器)是否小于 SIDE_TABLE_DEALLOCATING){
second |= SIDE_TABLE_DEALLOCATING;do_dealloc = true
}
else if(迭代器->second & SIDE_TABLE_RC_PINNED > 0){
計數(shù)器-=SIDE_TABLE_RC_ONE
}
結(jié)束,解開鎖
if(do_dealloc && performDealloc){
調(diào)用對象的dealloc方法:
((void(*)(objc_object *, SEL))objc_msgSend)(this, SEL_dealloc)
}
返回do_dealloc
如果調(diào)用了dealloc:
進行以下過程時,不能再創(chuàng)建有新的 __weak引用,否則會crash
- 遞歸調(diào)用父類的-dealloc
如果是 MRC 代碼,則需要手動釋放實例變量
- 最后調(diào)用NSObject的dealloc
NSObject的dealloc會調(diào)用_objc_rootDealloc(self);
_objc_rootDealloc(id obj)
if(obj是否活著){
調(diào)用obj->rootDealloc()
}else{
crash
}
objc_object::rootDealloc()
if(this是使用TaggedPointer優(yōu)化){ 直接返回 }
if(不需要處理object_dispose的所有內(nèi)容){ free(this)然后返回 }
調(diào)用 object_dispose((id)this)
object_dispose(id obj)
if(!obj){ 直接返回 }
調(diào)用 objc_destructInstance()
objc_destructInstance()
objc_destructInstance做的事情比較多痰驱,先說objc_destructInstance的內(nèi)容肩民,內(nèi)部調(diào)用的方法后面再細(xì)說:
if(如果需要為 C++ 的實例變量們(iVars)調(diào)用析構(gòu)器){
調(diào)用object_cxxDestruct(obj)
}
if(通過obj->hasAssociatedObjects()判斷是否需要解除所有使用runtime Associate關(guān)聯(lián)的對象){
//如果是TaggedPointer優(yōu)化蔽豺,那這個方法也會返回true
調(diào)用_object_remove_assocations(obj)
}
調(diào)用objc_clear_deallocating()
調(diào)用 free() 返回nil
object_cxxDestruct(obj)
if(!obj){return;}
if(!isTaggedPointer){return;}
調(diào)用object_cxxDestructFromClass(obj, obj->ISA());
內(nèi)部會遞歸判斷自己和父類是否有.cxx_destruct方法,有的話則調(diào)用.cxx_destruct
.cxx_destruct
ARC下?lián)碛袑嵗兞坎艜羞@個方法,通過Clang CodeGen生成,MRC都需要手動release所以不需要
ARC下會遍歷當(dāng)前對象所有的實例變量通過objc_storeStrong() release掉
具體實現(xiàn)過程:https://blog.sunnyxx.com/2014/04/02/objc_dig_arc_dealloc/
_object_remove_assocations(obj)
關(guān)聯(lián)對象都存放在AssociationsHashMap中,以obj為key,以存放關(guān)聯(lián)對象的ObjectAssociationMap為value,具體操作就是把ObjectAssociationMap中的所有對象對應(yīng)的Allocator拿出來,作為參數(shù)發(fā)送給ReleaseValue(),然后調(diào)用objc_release()再對關(guān)聯(lián)對象發(fā)送release
objc_clear_deallocating()
if(isa.nonpointer){
調(diào)用sidetable_clearDeallocating()把對象的weak指針置nil,把對象的計數(shù)引用移除
}
if (isa.weakly_referenced(是否有過弱引用) || isa.has_sidetable_rc(是否因為計數(shù)太大有多個sidetable)){
調(diào)用clearDeallocating_slow();內(nèi)部再分開判斷各自實現(xiàn)sidetable_clearDeallocating的內(nèi)容
}