iOS開發(fā)--“自動釋放池塊”降低內(nèi)存峰值

Objective-C對象的生命期取決于其引用的計數(shù)羡宙。在Objective-C的引用計數(shù)構(gòu)架中汽抚,有一種特征叫做“自動釋放池塊”(autorelease pool)殊轴。釋放隊(duì)形有兩個方式:以后總是調(diào)用release方式,時期保留計數(shù)立即遞減:另一種是調(diào)用autorelease方法财边,將其加入”自動釋放池“時氧苍,系統(tǒng)會將其中多個對象發(fā)送release消息夜矗。
自動釋放池的原理.

  存入到自動釋放池中的對象,在自動釋放池被銷毀的時候.會自動調(diào)用存儲在該自動釋放池中的所有對象的release方法.

   可以解決的問題:

   將創(chuàng)建的對象,存入到自動釋放池之中. 就不再需要手動的relase這個對象了.
   因?yàn)槌刈愉N毀的時候 就會自動的調(diào)用池中所有的對象的relase。
    創(chuàng)建自動釋放池的語法運(yùn)用如下:

@autoreleasepool {
//.......
}

    如果在沒有創(chuàng)建自動釋放池的情況下給對象發(fā)送autorelease消息让虐,那么控制臺就會輸出這樣一條消息:

Objective 0xabcd0123 of class __NSCFString autorelease
with no pool in place - just leaking - break on objc

autoreleaseNoPool() to doing
然而紊撕,一般情況下無需擔(dān)心自動釋放池的創(chuàng)建問題。Mac OS X 與iOS應(yīng)用程序分別運(yùn)用于Cocoa及Cocoa Touch環(huán)境中個赡突。系統(tǒng)和會自動創(chuàng)建一些路線对扶,比如說主線或者”大中樞派發(fā)“(Grand Central Dispatch,GCD)機(jī)制中的線程,這些線程默認(rèn)都是自動釋放惭缰,每次執(zhí)行”事件循環(huán)“時浪南,就會進(jìn)將其清空。因此漱受,不需要自己來創(chuàng)建“自動釋放吃”同塵個只有一個地方需要創(chuàng)建自動釋放池络凿,那就在main函數(shù)里。我們用自動釋放池來包裹應(yīng)用程序的主入口。比方說絮记。iOS程序的面函數(shù)經(jīng)常這樣寫:
int main(int argh, char *argv[]) {
@autoreleasepool {
return UIApplicationMain(argh,argv,nil,@"EOCAppDelegate");
}
}
從技術(shù)角度來看摔踱,不是非得有個“自動釋放池”才行。應(yīng)為塊的末尾敲好就是應(yīng)用程序的終結(jié)處怨愤,二此時操作系統(tǒng)會把程序所占的全部內(nèi)存全都釋放掉派敷,雖然如此,但是如果不寫這個塊的話撰洗,那么有UIApplicationMain函數(shù)所自動釋放的那些對象篮愉,就沒有自動釋放池可以容納了,于是西戎會發(fā)出警告信息來表明這一情況了赵。所以說,這個吃可以理解成最外圍捕捉自動釋放對象所用的池甸赃。
下面這段代碼中的話括號定義了自動化四方吃的范圍柿汛。自動釋放池于左括號處創(chuàng)建,并于對應(yīng)右括號處清空埠对。位于自動釋放池中的對象络断,將在此范圍末尾處收到release的消息。自動釋放吃可以嵌套项玛。系統(tǒng)在自動該釋放對象的時候貌笨,會把它放到最內(nèi)層的池里。比方說:
@autoreleasepool {
NSString *string = [NSString stringWithFormat:@"1 - %i",1];
@autoreleasepool {
NSNumber *number = [NSNumber numberWithInt:1];
}
}
使用注意

只有在自動釋放池中調(diào)用了對象的autorelease方法,這個對象才會被存儲到這個自動釋放池之中.

如果只是將對象的創(chuàng)建代碼寫在自動釋放之中,而沒有調(diào)用對象的autorelease方法.是不會將這個對象存儲到這個自動釋放池之中的.
對象的創(chuàng)建可以在自動釋放池的外面,在自動釋放池之中,調(diào)用對象的autorelease方法,就可以將這個對象存儲到這個自動釋放池之中.

如果對象的autorelease方法的調(diào)用放在自動釋放池的外面,是無法將其存儲的這個自動釋放池之中的.

autorelease 的調(diào)用只有放在自動釋放池之中 才可以講其存儲到自動釋放池之中, 對象的創(chuàng)建可以在外面

當(dāng)自動釋放池結(jié)束的時候.僅僅是對存儲在自動釋放池中的對象發(fā)送1條release消息 而不是銷毀對象.

如果在自動釋放池中,調(diào)用同1個對象的autorelease方法多次.就會將對象存儲多次到自動釋放池之中.

在自動釋放池結(jié)束的時候.會為對象發(fā)送多條release消息.
所以,1個自動釋放池之中,只autorelease1次,只將這個對象放1次, 否則就會出現(xiàn)野指針錯誤.
如果在自動釋放池中,調(diào)用了存儲到自動釋放中的對象的release方法.

在自動釋放池結(jié)束的時候,還會再調(diào)用對象的release方法.
這個時候就有有可能會造成野指針操作.
將對象存儲到自動釋放池,并不會使對象的引用計數(shù)器+1 所以其好處就是:創(chuàng)建對象將對象存儲在自動釋放池,就不需要在寫個release了.

自動釋放池可以嵌套.

調(diào)用對象的autorelease方法,會講對象加入到當(dāng)前自動釋放池之中
只有在當(dāng)前自動釋放池結(jié)束的時候才會像對象發(fā)送release消息.
autorelease的應(yīng)用場景.

創(chuàng)建對象,將對象存儲到自動釋放池之中. 就不需要再去手動的realse锥惋。

我們一般情況下,會為我們的類寫1個類方法,用來讓外界調(diào)用類方法來快速的得到1個對象.

規(guī)范:使用類方法得到的對象,要求這個對象就已經(jīng)被autorelease過了.

提供1個類方法來快速的得到1個對象.

規(guī)范
這個類方法以類名開頭. 如果沒有參數(shù)就直接是類名 如果有參數(shù)就是 類名WithXX:
使用類方法得到的對象,要求這個對象就已經(jīng)被autorelease過了.

  • (instancetype)person
    {
    return [[[self alloc] init] autorelease];
    }
    以下是我整理的需要注意的事項(xiàng):
    (1)在自動釋放池@autoreleasepool{}中alloc一個對象后,仍然需要用[p1 autorelease];只是這個語句和[p1 release];不同开伏,后者表示把p1的retainCount-1膀跌,而前者僅僅表示把p1放到自動釋放池中返回一個self,自動釋放池結(jié)束銷毀時固灵,統(tǒng)一對里面的對象引用計數(shù)retainCount-1捅伤。

(2)@autoreleasepool{}可以隨意創(chuàng)建,也可以嵌套使用巫玻。

(3)不管這個對象是在自動釋放池內(nèi)還是外創(chuàng)建的丛忆,只要在自動釋放池內(nèi)寫一個[p1 autorelease];p1就會被放到自動釋放池中。注意autorelease是一個方法仍秤,且只有在自動釋放池中使用才有效熄诡。

(4)如果把一個對象重復(fù)加到自動釋放池如[p1 autorelease];[p1 autorelease];,那么會出錯诗力。原因是:加載幾次粮彤,屆時自動釋放池就會用[p1 release];釋放幾次,但是由于這兩個加載的對象其實(shí)是一個對象同樣地址,所以第一次自動釋放正確导坟,第二次自動釋放時發(fā)現(xiàn)已經(jīng)被釋放了屿良,所以p1就變成了野指針。

(5)以下是自動釋放池嵌套的使用規(guī)則和注意點(diǎn)惫周。
[objc] view plain copy 在CODE上查看代碼片派生到我的代碼片

import <Foundation/Foundation.h>

import "Person.h"

int main(int argc, const charchar * argv[]) {

Person *p1=[[Person alloc]init];  
@autoreleasepool {  
    @autoreleasepool {  
        [p1 autorelease];  
    }//在執(zhí)行到此處時尘惧,p1被自動釋放  
}  
  
//以下代碼有錯誤  
@autoreleasepool {  
    [p1 autorelease];//此時p1被加入進(jìn)來  
    @autoreleasepool {  
        [p1 autorelease];//被重復(fù)加載進(jìn)來,但仍然同一個  
    }//此處递递,p1被自動釋放了喷橙,所以第一次加進(jìn)來的那個也被釋放了,因?yàn)槭峭粋€對象  
}//所以此處在調(diào)用[p1 release];時就出現(xiàn)報錯:野指針  
  
return 0;  

}

(6)@autoreleasepool的應(yīng)用:如果需要在方法中創(chuàng)建對象登舞,并把這個對象作為返回值贰逾,那么可以在這個方法中使用[*** autorelease];把它加入到自動釋放池中,否則菠秒,直接用[*** release];來匹配alloc的話疙剑,在該方法中就已經(jīng)把這個對象alloc和release了一遍相當(dāng)于釋放了,那么所謂的返回對象返回的時一個野指針(沒有指向任何對象)践叠。當(dāng)然言缤,調(diào)用這個方法的代碼頁需要寫在自動釋放池作用域內(nèi)才生效。

(7)接上面禁灼。返回對象的那個方法中管挟,創(chuàng)建對象不建議直接用類名,而是用self弄捕,否則如果存在子類調(diào)用會崩潰僻孝。如Car *car1=[[self alloc]init];

(8)其實(shí)諸如NSString *str1=[NSString stringWithFormat:@"%@",@"hello"];也是調(diào)用了一個方法,并且返回了一個字符串對象守谓。比照(6)和(7)我們得知這個stringWithFormat應(yīng)該也是順便返回了一個autorelease皮璧。

(9)在ARC機(jī)制中,我們用@property聲明的成員變量分飞,建議用strong代替之前手動管理內(nèi)存時的retain悴务,雖然后者仍然可以使用。因?yàn)槲覀冊贏RC中內(nèi)存管理就是看是否有強(qiáng)指針指向?qū)ο笃┟ǎ缬芯筒换厥昭堕埽鐩]有就回收。所以強(qiáng)指針是strong染服,相反是weak别洪。而基本數(shù)據(jù)類型我們還是習(xí)慣用assign。

(10)雖然Xcode提供了非ARC轉(zhuǎn)換成ARC的柳刮,很少有把整個非ARC轉(zhuǎn)換成ARC的挖垛。如果我們導(dǎo)入第三方庫時痒钝,需要非ARC和ARC共存,即我們系統(tǒng)默認(rèn)是ARC痢毒,我們需要讓系統(tǒng)不要去管這個非ARC的第三方庫送矩,如下設(shè)置:雙擊響應(yīng)的.m文件,輸入-fno-objc-arc回車即可哪替。

(11)順便栋荸,當(dāng)出現(xiàn)兩個類循環(huán)引用的話(也就是A要包含B,B要包含A凭舶,即A對象要作為B的變量晌块,B對象要作為A的變量),只需要把一方的strong改成weak帅霜,并且在響應(yīng)的.h文件中把#import ".h"改成Class ***匆背。如果因?yàn)楦某蒀lass ***而無法使用那個類的方法的話,只需要在它的.m文件中#import“.h”文件即可身冀,這個因?yàn)椴皇窃?h文件中導(dǎo)入所以不沖突钝尸。
這就是我整理的關(guān)于Autorelease的使用以及“自動釋放池塊”降低內(nèi)存峰值的使用方法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市闽铐,隨后出現(xiàn)的幾起案子蝶怔,更是在濱河造成了極大的恐慌奶浦,老刑警劉巖兄墅,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異澳叉,居然都是意外死亡隙咸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門成洗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來五督,“玉大人,你說我怎么就攤上這事瓶殃〕浒” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵遥椿,是天一觀的道長基矮。 經(jīng)常有香客問我,道長冠场,這世上最難降的妖魔是什么家浇? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮碴裙,結(jié)果婚禮上钢悲,老公的妹妹穿的比我還像新娘点额。我一直安慰自己,他們只是感情好莺琳,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布还棱。 她就那樣靜靜地躺著,像睡著了一般芦昔。 火紅的嫁衣襯著肌膚如雪诱贿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天咕缎,我揣著相機(jī)與錄音珠十,去河邊找鬼。 笑死凭豪,一個胖子當(dāng)著我的面吹牛焙蹭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播嫂伞,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼孔厉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了帖努?” 一聲冷哼從身側(cè)響起撰豺,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拼余,沒想到半個月后污桦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡匙监,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年凡橱,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片亭姥。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡稼钩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出达罗,到底是詐尸還是另有隱情坝撑,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布粮揉,位于F島的核電站巡李,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏滔蝉。R本人自食惡果不足惜击儡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝠引。 院中可真熱鬧阳谍,春花似錦蛀柴、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至训貌,卻和暖如春制肮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背递沪。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工豺鼻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人款慨。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓儒飒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親檩奠。 傳聞我的和親對象是個殘疾皇子桩了,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 內(nèi)存管理 簡述OC中內(nèi)存管理機(jī)制。與retain配對使用的方法是dealloc還是release埠戳,為什么井誉?需要與a...
    丶逐漸閱讀 1,948評論 1 16
  • 29.理解引用計數(shù) Objective-C語言使用引用計數(shù)來管理內(nèi)存,也就是說整胃,每個對象都有個可以遞增或遞減的計數(shù)...
    Code_Ninja閱讀 1,470評論 1 3
  • iOS內(nèi)存管理 概述 什么是內(nèi)存管理 應(yīng)用程序內(nèi)存管理是在程序運(yùn)行時分配內(nèi)存(比如創(chuàng)建一個對象,會增加內(nèi)存占用)與...
    蚊香醬閱讀 5,694評論 8 119
  • 我生君晚生 君成我心老 恨熟不同時 感錯才知曉 君來我已去 我來君已往 恨遇不逢時 日日與君好 君來之吾悅 君去之...
    琪人書蘭閱讀 227評論 0 0
  • 親愛的小蘋果(小屁股): 我們的相處就如我對你的稱呼一樣颗圣,大家都應(yīng)該想象得出我們是如此多姿的相處。 這一年中你已增...
    夕陽老去西風(fēng)漸緊閱讀 288評論 2 1