生對(duì)死,alloc
對(duì)dealloc
alloc
經(jīng)歷了一些周折才調(diào)用calloc
,開(kāi)辟內(nèi)存空間.
dealloc
也一樣經(jīng)歷了一些周折才調(diào)用free
,釋放了內(nèi)存空間.
1. dealloc流程
調(diào)用棧如上圖.其實(shí)可以將分支合并:
isa.nonpointer&&!isa.weakly_referenced&&!isa.has_assoc&& !isa.has_cxx_dtor&&!isa.has_sidetable_rc
- 條件1:isa.nonpointer
是否是支持nonpointer
的isa
,不支持直接free
;(不支持nonpointer
的isa
,下面的條件都不必看)
- 條件2:isa.has_cxx_dtor
是否有C++的析構(gòu)函數(shù),為真,則要調(diào)用析構(gòu)函數(shù);
- 條件3:isa.has_assoc
是否有關(guān)聯(lián)屬性,為真,則要解除關(guān)聯(lián)屬性;
- 條件4:isa.weakly_referenced
是否有weak指針
指向該對(duì)象,為真,則要將所有指向該對(duì)象的weak指針
全部置為nil;
- 條件5:isa.has_sidetable_rc
是否開(kāi)啟了Sidetable
來(lái)儲(chǔ)存該對(duì)象的retainCount
,為真,則要將該對(duì)象對(duì)應(yīng)的Sidetable
內(nèi)儲(chǔ)存的retainCount
清除.
5個(gè)條件全部走完,再調(diào)用free
,收工.
2. 哪里不對(duì)?
問(wèn)題1:ARC環(huán)境下不用書(shū)寫對(duì)象對(duì)自己實(shí)例變量引用解除的代碼,為什么流程中不見(jiàn)對(duì)自己實(shí)例變量解除引用的代碼?
答:一個(gè)方法,一個(gè)標(biāo)記.
@interface PGCustomClass : NSObject
@property(nonatomic,copy)NSString * name;
@end
生成PGCustomClass
對(duì)象時(shí),看initInstanceIsa
的參數(shù):
@interface PGCustomClass2 : NSObject
@end
生成PGCustomClass
對(duì)象時(shí),看initInstanceIsa
的參數(shù):
- 一個(gè)標(biāo)記
很明顯,帶實(shí)例變量的類的obj
->isa.has_cxx_dtor
==1;
很明顯,不帶實(shí)例變量的類的obj
->isa.has_cxx_dtor
==0;
實(shí)例變量(是不是屬性格式無(wú)所謂).
obj
->isa.has_cxx_dtor
,追溯根源還是來(lái)自類的bits->flags
.
- 一個(gè)方法
在PGCustomClass
和PGCustomClass2
內(nèi)加入以下代碼,打印方法列表:
- (void)logMethods
{
unsigned int count;
Method *methods = class_copyMethodList([self class], &count);
for (int i = 0; i < count; i++)
{
Method method = methods[i];
SEL selector = method_getName(method);
NSString * name = NSStringFromSelector(selector);
NSLog(@"方法名:%@",name);
}
}
PGCustomClass:
logMethods
.cxx_destruct
PGCustomClass2:
logMethods
很明顯,帶實(shí)例變量的類多出一個(gè).cxx_destruct
方法,是編譯器加的.
一個(gè)標(biāo)記+一個(gè)方法==>如下效果:
isa.has_cxx_dtor==1;
└─object_cxxDestructFromClass
└─.cxx_destruct
isa.has_cxx_dtor==1;
才會(huì)調(diào)用object_cxxDestructFromClass
,進(jìn)而調(diào)用.cxx_destruct
.
.cxx_destruct
方法內(nèi)就是做了對(duì)象對(duì)自己實(shí)例變量的引用解除
static void object_cxxDestructFromClass(id obj, Class cls)
{
void (*dtor)(id);
// Call cls's dtor first, then superclasses's dtors.
for ( ; cls; cls = cls->superclass) {
if (!cls->hasCxxDtor()) return;
dtor = (void(*)(id))
lookupMethodInClassAndLoadCache(cls, SEL_cxx_destruct);
if (dtor != (void(*)(id))_objc_msgForward_impcache) {
if (PrintCxxCtors) {
_objc_inform("CXX: calling C++ destructors for class %s",
cls->nameForLogging());
}
(*dtor)(obj);
}
}
}
isa.has_cxx_dtor
除了標(biāo)記當(dāng)前類是否有C++的析構(gòu)函數(shù)外,被賦予了其他公用:標(biāo)記對(duì)象是否有實(shí)例變量;
為什么有實(shí)例變量的類才加標(biāo)記
和方法
呢?
原因也很簡(jiǎn)單,因?yàn)橹挥羞@樣的類生成的對(duì)象才會(huì)有
實(shí)例變量,對(duì)象有實(shí)例變量才需要
解除引用.
問(wèn)題2:ARC環(huán)境下-dealloc
內(nèi)不能書(shū)寫[super dealloc]
,為什么流程中也不見(jiàn)調(diào)用父類的dealloc
?
由上面的邏輯推算,[super dealloc]
也是編譯器加的.詳情請(qǐng)戳