前一段時(shí)間和一同事聊天,聊到一個(gè)話題另玖,關(guān)于學(xué)習(xí)曲線的的話題绘盟,雖說有很多不一致,但有一點(diǎn)我們一致認(rèn)同的深度決定高度呼巷!為此,我再次看了這本書(Objective-C 高級(jí)編程)赎瑰。
該書從以下三部分出發(fā)王悍,自動(dòng)引用計(jì)數(shù)、Blocks餐曼、Grand Central Dispatch压储,在源代碼的基礎(chǔ)上加以解說鲜漩,深入剖析。 非常建議購(gòu)買看原版書籍集惋!非常值得吃兴疲看,因?yàn)榈谝槐榭赡芸床欢涡蹋?/p>
在此喉祭,我以筆記的形式,邊學(xué)習(xí)雷绢,邊記錄泛烙,便于自己堅(jiān)持。
自動(dòng)引用計(jì)數(shù)
什么是自動(dòng)引用計(jì)數(shù)
定義:自動(dòng)引用計(jì)數(shù)是指內(nèi)存管理中對(duì)引用采取的自動(dòng)計(jì)數(shù)的技術(shù)翘紊。
注意點(diǎn):在 LLVM 編譯器中設(shè)置 ARC 為有效狀態(tài)胶惰,就無需再次輸入 retain 或者是 release 代碼。
好處:這在降低程序奔潰霞溪,內(nèi)存泄露等風(fēng)險(xiǎn)的同時(shí)孵滞,很大程度上減少了開發(fā)程序的工作量。
內(nèi)存管理 / 引用計(jì)數(shù)
2.1 引用計(jì)數(shù)的機(jī)制理解
以經(jīng)典的開燈例子舉例鸯匹,在辦公室內(nèi)至少有一人保持開燈狀態(tài)坊饶,無人時(shí)保持關(guān)燈狀態(tài)
最早進(jìn)入辦公室的人 ===> 開燈 ==== > 生成對(duì)象
之后進(jìn)入辦公室的人 ===> 需要照明 ==== > 持有對(duì)象
下班離開辦公室的人 ===> 不需要照明 ==== > 釋放對(duì)象
最后下班離開辦公室的人===> 關(guān)燈 ==== > 廢棄對(duì)象
中間無論多少人,只要遵循進(jìn)來就需要照明殴蓬,走就不要照明匿级。這樣辦公室的照明就可以得到很好的管理;同理使用引用計(jì)數(shù)功能染厅,對(duì)象也能夠得到很好的管理痘绎。
注意:release方法
當(dāng)引用計(jì)數(shù)等于零時(shí)會(huì)自動(dòng)使用dealloc方法
。
原則:
- 自己生成的對(duì)象肖粮,自己持有孤页。
- 非自己生成的對(duì)象,自己也能持有涩馆。
- 不再需要自己持有的對(duì)象時(shí)釋放行施。
- 非自己持有的對(duì)象無法釋放。
** 2.2魂那、alloc,retain,release的實(shí)現(xiàn)的理解 **
由于 NSObject 的源碼沒有公開蛾号,此利用 Xcode 的調(diào)試器和 iOS 大概追溯其實(shí)現(xiàn)過程。
- alloc
+alloc
+allocWithZone:
Class_createInstance
calloc
alloc類方法首先調(diào)用 allocWithZone:類方法涯雅,然后調(diào)用 class_instance 函數(shù)鲜结,最后通過 calloc 來分配內(nèi)存塊。這樣就相當(dāng)于 alloc 的實(shí)現(xiàn)啦。
- retain精刷、release
int __CFDoExternRefOpreation(uintptr_t op, id obj) {
CFBasicHashRef table = 獲取對(duì)應(yīng)的是散列表obj(); // 獲取對(duì)應(yīng)的是散列表
int count;
switch (op) {
case OPREATION_retainCount:
count = CFBasicHashGetCountOfKey(table, obj);
return count;
case OPREATION_retain:
count = CFBasicHashAddVlaue(table, obj);
return count;
case OPREATION_release:
count = CFBasicHashRemoveValue(table, obj);
// count == 0的時(shí)候拗胜,調(diào)用 dealloc
return 0 == count;
}
}
然后真正的對(duì)象實(shí)現(xiàn)的方法也許如下:
- (NSUInteger)reatainCount
{
return (NSUInteger) __CFDoExternRefOpreation(OPREATION_retainCount, self);
}
- (id)retain
{
return (id) __CFDoExternRefOpreation(OPREATION_retain, self);
}
- (void)release
{
return __CFDoExternRefOpreation(OPREATION_release, self);
}
蘋果的實(shí)現(xiàn)大概是采用 散列表(引用計(jì)數(shù)表)來管理引用計(jì)數(shù)器。
這樣做的好處:
對(duì)象用內(nèi)存筷發(fā)分配無需考慮內(nèi)存塊的頭部贬养。
引用計(jì)數(shù)表各記錄都有內(nèi)存塊地址挤土,可從各個(gè)記錄追訴哦到各對(duì)象的的內(nèi)存塊琴庵。
同時(shí)檢測(cè)內(nèi)存泄露時(shí)误算,很方便檢測(cè)各對(duì)象的持有者是否存在
以上大致是 retain 、release 的理解迷殿,NSObject 在實(shí)例化該方法的時(shí)候先去調(diào)用一個(gè)類似 CFDoExternRefOpreation的函數(shù)儿礼,然后實(shí)現(xiàn)相應(yīng)的方法 CFBasicHashRemoveValue 或 CFBasicHashAddVlaue,通過CFBasicHashRef table (引用計(jì)數(shù)表)整體的管理它的引用計(jì)數(shù)庆寺,來實(shí)現(xiàn) retain 或 release蚊夫。這就是大致的實(shí)現(xiàn)過程啦。