iOS開發--“自動釋放池塊”降低內存峰值

Objective-C對象的生命期取決于其引用的計數。在Objective-C的引用計數構架中,有一種特征叫做“自動釋放池塊”(autorelease pool)。釋放隊形有兩個方式:以后總是調用release方式,時期保留計數立即遞減:另一種是調用autorelease方法,將其加入”自動釋放池“時,系統會將其中多個對象發送release消息。
自動釋放池的原理.

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

   可以解決的問題:

   將創建的對象,存入到自動釋放池之中. 就不再需要手動的relase這個對象了.
   因為池子銷毀的時候 就會自動的調用池中所有的對象的relase。
    創建自動釋放池的語法運用如下:

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

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

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

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

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

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

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

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

當自動釋放池結束的時候.僅僅是對存儲在自動釋放池中的對象發送1條release消息 而不是銷毀對象.

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

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

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

自動釋放池可以嵌套.

調用對象的autorelease方法,會講對象加入到當前自動釋放池之中
只有在當前自動釋放池結束的時候才會像對象發送release消息.
autorelease的應用場景.

創建對象,將對象存儲到自動釋放池之中. 就不需要再去手動的realse。

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

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

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

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

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

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

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

(4)如果把一個對象重復加到自動釋放池如[p1 autorelease];[p1 autorelease];,那么會出錯。原因是:加載幾次,屆時自動釋放池就會用[p1 release];釋放幾次,但是由于這兩個加載的對象其實是一個對象同樣地址,所以第一次自動釋放正確,第二次自動釋放時發現已經被釋放了,所以p1就變成了野指針。

(5)以下是自動釋放池嵌套的使用規則和注意點。
[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];  
    }//在執行到此處時,p1被自動釋放  
}  
  
//以下代碼有錯誤  
@autoreleasepool {  
    [p1 autorelease];//此時p1被加入進來  
    @autoreleasepool {  
        [p1 autorelease];//被重復加載進來,但仍然同一個  
    }//此處,p1被自動釋放了,所以第一次加進來的那個也被釋放了,因為是同一個對象  
}//所以此處在調用[p1 release];時就出現報錯:野指針  
  
return 0;  

}

(6)@autoreleasepool的應用:如果需要在方法中創建對象,并把這個對象作為返回值,那么可以在這個方法中使用[*** autorelease];把它加入到自動釋放池中,否則,直接用[*** release];來匹配alloc的話,在該方法中就已經把這個對象alloc和release了一遍相當于釋放了,那么所謂的返回對象返回的時一個野指針(沒有指向任何對象)。當然,調用這個方法的代碼頁需要寫在自動釋放池作用域內才生效。

(7)接上面。返回對象的那個方法中,創建對象不建議直接用類名,而是用self,否則如果存在子類調用會崩潰。如Car *car1=[[self alloc]init];

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

(9)在ARC機制中,我們用@property聲明的成員變量,建議用strong代替之前手動管理內存時的retain,雖然后者仍然可以使用。因為我們在ARC中內存管理就是看是否有強指針指向對象,如有就不回收,如沒有就回收。所以強指針是strong,相反是weak。而基本數據類型我們還是習慣用assign。

(10)雖然Xcode提供了非ARC轉換成ARC的,很少有把整個非ARC轉換成ARC的。如果我們導入第三方庫時,需要非ARC和ARC共存,即我們系統默認是ARC,我們需要讓系統不要去管這個非ARC的第三方庫,如下設置:雙擊響應的.m文件,輸入-fno-objc-arc回車即可。

(11)順便,當出現兩個類循環引用的話(也就是A要包含B,B要包含A,即A對象要作為B的變量,B對象要作為A的變量),只需要把一方的strong改成weak,并且在響應的.h文件中把#import ".h"改成Class ***。如果因為改成Class ***而無法使用那個類的方法的話,只需要在它的.m文件中#import“.h”文件即可,這個因為不是在.h文件中導入所以不沖突。
這就是我整理的關于Autorelease的使用以及“自動釋放池塊”降低內存峰值的使用方法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,247評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,520評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,362評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,805評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,541評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,896評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,887評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,062評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,608評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,356評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,555評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,077評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,769評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,175評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,489評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,289評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,516評論 2 379

推薦閱讀更多精彩內容

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