第29條 理解引用計數(shù)
引用計數(shù)每次alloc亮蒋、init之后陈肛,引用計數(shù)至少增加1唆鸡,因為init里可能有別的對象也引用了該對象名斟,所以說只能說至少增加1脑慧。
setter方法:
- (void)setName:(NSString *)name
{
[name retain];
[_name release];
_name = name;
}
不能先寫[_name release];
,一定要先retain砰盐,因為如果name和_name指向同一塊內(nèi)存闷袒,那相當(dāng)于把name釋放掉了,后面retain已經(jīng)沒效果了岩梳。
第30條 以ARC簡化引用計數(shù)
CoreFoundation對象不歸ARC管理囊骤,開發(fā)者需要手動調(diào)用CFRetain和CFRelease。
第31條 在dealloc方法里只釋放引用并解除監(jiān)聽
不要在dealloc方法里調(diào)用一些比較耗時(如異步)的方法冀值,因為對象可能會在方法完成前已經(jīng)釋放了也物。另外dealloc里的線程可能不是主線程,因為此時對象已經(jīng)處在回收的狀態(tài)了列疗。
第32條 編寫“異常安全代碼”時留意內(nèi)存管理問題
在try塊中滑蚯,如果一個對象被強(qiáng)引用了,在釋放該對象前拋出異常抵栈,那么除非catch塊能處理此問題告材,否則對象所占的內(nèi)存就泄露了。
ARC下問題可能會更嚴(yán)重:
在開啟ARC之后正常情況下一切和內(nèi)存有關(guān)的申請和釋放操作皆不用你關(guān)心了古劲,ARC全全幫你包辦了斥赋。但是還有極少數(shù)的情況下,編譯器無法為你生成合適的ARC額外代碼绢慢,比如obj-c異常就是這么一個例子灿渴。
話句話說在ARC中異常可能會導(dǎo)致對象的內(nèi)存泄露胰舆。因為ARC是顆辽叮化對象為一個文件:即可以在obj-c文件上啟用ARC.所以我們可以選擇性的在編譯某個文件上加上-fobjc-arc-exceptions選項,如果開啟了該選項缚窿,則ARC會額外為異常中的對象申請和釋放操作添加代碼棘幸,保證異常中ARC管理的對象也不會造成內(nèi)存泄露。當(dāng)然這樣一來缺點就是可能會生成大量平尘肓悖可能根本用不到的代碼误续。(只有發(fā)生異常才會執(zhí)行)
所以我們可以只在必要的obj-c文件上啟用-fobjc-arc-exceptions標(biāo)志,而其他文件禁用該標(biāo)志扫茅,這樣才可以做到萬無一失蹋嵌。
第33條 以弱引用避免保留環(huán)
weak和assign的區(qū)別
第34條 以自動釋放池降低內(nèi)存峰值
主線程或GCD的線程中,都存在自動釋放池葫隙,每次執(zhí)行Event Loop時栽烂,就會將其清空。
第35條 用僵尸對象調(diào)試內(nèi)存管理問題
- 向已經(jīng)被釋放的對象發(fā)送消息是不安全的,有時會崩潰腺办,有時不會焰手,取決于該對象的內(nèi)存是否已經(jīng)被其他內(nèi)容所覆寫。
- 啟用了僵尸對象(Zombie object)后怀喉,運行期系統(tǒng)會把所有已經(jīng)被回收的對象轉(zhuǎn)為僵尸對象书妻,而不會真正的回收它們。這種對象所在的核心內(nèi)存無法重用躬拢,因此就無法被遭到覆寫躲履。僵尸對象收到消息后,會拋出異常估灿,準(zhǔn)確說明了發(fā)來的消息崇呵,并描述了回收之前的那個對象。
- 具體過程馅袁,就是如果檢測到僵尸對象已經(jīng)打開,就通過swizzle方法將dealloc交換荒辕,然后在里面copy一份原來的對象汗销,然后改類名為 NSZOmbie_MyClass。
- 系統(tǒng)會修改對象的isa指針抵窒,使其指向特殊的僵尸對象弛针,從而使對象變成僵尸對象。僵尸對象能夠響應(yīng)所有的選擇子李皇,響應(yīng)方式為:打印一條包含消息內(nèi)容及接收者的消息削茁,然后終止程序。
第36條 不要使用 retainCount
此方法即便在調(diào)試的時候也沒用掉房,原因是:它返回的保留計數(shù)只是某個時間點上的值茧跋,并未考慮到系統(tǒng)可能稍后就會把自動釋放池清空的情況。
如卓囚,錯誤代碼:
//問題1:若object已經(jīng)在自動釋放池里了瘾杭,稍后系統(tǒng)還會清空一次,會造成程序崩潰
//問題2:有時候系統(tǒng)會優(yōu)化哪亿,retainCount為1的時候就把對象釋放了粥烁,所有可能retainCount永遠(yuǎn)都不會為0
while ([object retainCount])
{
[object release];
}