iPhone內(nèi)存管理面面觀 自動(dòng)釋放與便捷方法
我們?cè)谇懊娼榻B過(guò)iPhone軟件的內(nèi)存管理如何有效控制“對(duì)象所有權(quán)與引用計(jì)數(shù)”,在這篇文章中我們將介紹“自動(dòng)釋放”(Auto release)與“便捷方法”(convenience method)。
51CTO推薦專題:iPhone應(yīng)用程序開(kāi)發(fā)初探
有時(shí)候一個(gè)所有者創(chuàng)建一個(gè)對(duì)象后,會(huì)立刻將該對(duì)象的指針傳遞給其它所有者。這時(shí),這個(gè)創(chuàng)建者不希望再擁有這個(gè)對(duì)象,但如果立刻給它發(fā)送一個(gè)release消息會(huì)導(dǎo)致這個(gè)對(duì)象被立刻釋放掉——這樣其它所有者還沒(méi)有來(lái)得及保留該對(duì)象。解決這個(gè)兩難問(wèn)題的方法是,給對(duì)象發(fā)送一個(gè)autorelease消息:這樣創(chuàng)建者不再擁有該對(duì)象的所有權(quán);該對(duì)象成為自動(dòng)釋放的對(duì)象,但是不會(huì)立刻被釋放掉;其它所有者可以有時(shí)間保留或復(fù)制該對(duì)象,并成為其唯一所有者。
我們來(lái)看一個(gè)自動(dòng)釋放的例子(代碼清單3-1)。一個(gè)所有者先用alloc方法創(chuàng)建一個(gè)對(duì)象;此時(shí)該所有者擁有這個(gè)對(duì)象,對(duì)象的引用計(jì)數(shù)為1。緊接著,所有者自動(dòng)釋放該對(duì)象;所有者此時(shí)已經(jīng)放棄了所有權(quán),但對(duì)象的引用計(jì)數(shù)在一段時(shí)間內(nèi)依然為1。我們可以看出自動(dòng)釋放的另一個(gè)好處:你不會(huì)因?yàn)樵诤竺嫱浗o對(duì)象發(fā)送release消息而造成內(nèi)存泄露。
代碼清單3-1
- -(Object*)returnAutoreleaseObject {
- Object* obj = [[Object alloc] init];
- return [obj autorelease];
- }
與自動(dòng)釋放相關(guān)的,有一大類構(gòu)造方法(constructor method),由它們構(gòu)造的對(duì)象直接就是自動(dòng)釋放的對(duì)象;這一類構(gòu)造方法叫做便捷方法。比如下面這句的字符串就是一個(gè)自動(dòng)釋放的對(duì)象,stringWithFormat:就是一個(gè)便捷方法。
- NSString* string = [NSString stringWithFormat:@”autoreleaseString”];
再舉幾個(gè)便捷方法的例子,方便讀者以后的開(kāi)發(fā)。
1.NSArray的arrayWithObjects:和arrayWithArray:。
2.UIImage的imageNamed:。
3.NSNumber的numberWithBool等。
現(xiàn)在我們已經(jīng)解釋了,autorelease方法會(huì)在一段時(shí)間以后釋放掉一個(gè)對(duì)象,在這段時(shí)間內(nèi)我們可以安全地使用該對(duì)象。那么這段時(shí)間究竟是多久呢?我們需要先更多地了解自動(dòng)釋放的機(jī)制,再來(lái)回答這個(gè)問(wèn)題。
讓我們先來(lái)看看自動(dòng)釋放池。自動(dòng)釋放池是NSAutoreleasePool的實(shí)例,其中包含了收到autorelease消息的對(duì)象。當(dāng)一個(gè)自動(dòng)釋放池自身被銷毀(dealloc)時(shí),它會(huì)給池中每一個(gè)對(duì)象發(fā)送一個(gè)release消息(如果你給一個(gè)對(duì)象多次發(fā)送autorelease消息,那么當(dāng)自動(dòng)釋放池銷毀時(shí),這個(gè)對(duì)象也會(huì)收到同樣數(shù)目的release消息)??梢钥闯?,一個(gè)自動(dòng)釋放的對(duì)象,它至少能夠存活到自動(dòng)釋放池銷毀的時(shí)候。
那么自動(dòng)釋放池何時(shí)被創(chuàng)建,又何時(shí)被銷毀呢?在每一個(gè)事件周期(event cycle)的開(kāi)始,系統(tǒng)會(huì)自動(dòng)創(chuàng)建一個(gè)自動(dòng)釋放池;在每一個(gè)事件周期的結(jié)尾,系統(tǒng)會(huì)自動(dòng)銷毀這個(gè)自動(dòng)釋放池。一般情況下,你可以理解為:當(dāng)你的代碼在持續(xù)運(yùn)行時(shí),自動(dòng)釋放池是不會(huì)被銷毀的,這段時(shí)間內(nèi)你也可以安全地使用自動(dòng)釋放的對(duì)象;當(dāng)你的代碼運(yùn)行告一段落,開(kāi)始等待用戶輸入(或者其它事件)時(shí),自動(dòng)釋放池就會(huì)被釋放掉,池中的對(duì)象都會(huì)收到一個(gè)release消息,有的可能會(huì)因此被銷毀。
到此為止,相信你已經(jīng)對(duì)自動(dòng)釋放的機(jī)制有了一個(gè)大體的了解。自動(dòng)釋放而非直接釋放,可以幫助你節(jié)省一些代碼量,提高開(kāi)發(fā)速度。但是它有一個(gè)直接的缺點(diǎn):它延緩了對(duì)象的釋放,在有大量自動(dòng)釋放的對(duì)象時(shí),會(huì)占用大量?jī)?nèi)存資源。因此,你需要避免將大量對(duì)象自動(dòng)釋放。并且,在以下兩種情況下,你需要手動(dòng)建立并手動(dòng)銷毀掉自動(dòng)釋放池:
1.當(dāng)你在主線程外開(kāi)啟其它線程時(shí):系統(tǒng)只會(huì)在主線程中自動(dòng)生成并銷毀掉自動(dòng)釋放池。
2.當(dāng)你在短時(shí)間內(nèi)制造了大量自動(dòng)釋放對(duì)象時(shí):及時(shí)地銷毀有助于有效利用iPad上有限地內(nèi)存資源。
【編輯推薦】