autorelease專題

前言

Objective-C 對象的聲明周期取決于其引用計數(shù)。釋放對象有兩種方式:

  • 調(diào)用 release 方法坚洽,使其保留計數(shù)立即遞減
  • 調(diào)用 autorelease 方法糜工,將其加入自動釋放池中。清空自動釋放池時夫壁,系統(tǒng)會向其中的對象發(fā)送 release 消息。

那么問題來了庆械,自動釋放池什么時候清空呢薇溃。下面我們詳細(xì)介紹下 Autorelease pool。


autorelease 對象何時釋放缭乘。

autorelease 對象會在 autoreleasepool 清空時收到 release 消息沐序。

  • 系統(tǒng)創(chuàng)建的線程中(如主線程和global queue),默認(rèn)都有自動釋放池堕绩,當(dāng)前的 runloop 迭代結(jié)束時策幼,會將其清空。
  • 手動添加 autoreleasepool 逛尚,會在當(dāng)前作用域大括號結(jié)束時清空垄惧。

手動添加 autoreleasepool

下面這段代碼中刁愿,花括號定義了自動釋放池的范圍绰寞,自動釋放池于左括號處創(chuàng)建,于右括號處自動清空铣口。位于此范圍內(nèi)的對象滤钱,將在此范圍末尾處收到 release 消息。

@autoreleasepool{
         // ...
}

自動釋放池可以嵌套脑题,本例中的兩個對象都是由類的工廠方法所創(chuàng)建件缸,這樣創(chuàng)建的對象會自動釋放,NSString 類型的對象放在外圍的釋放池中叔遂,NSNumber 類型的對象則放在里層的釋放池中他炊。

@autoreleasepool{
        NSString *string = [NSString stringWithFormat:@"1 = %i",1];
        @autoreleasepool {
            NSNumber *number = [NSNumber numberWithInt:1];
        }
}

autoreleasepool 用法

一般情況下無須手動創(chuàng)建自動釋放池。

系統(tǒng)會自動創(chuàng)建一些線程已艰,比如主線程和GCD機制中的線程痊末,這些線程默認(rèn)都有自動釋放池,每次開始一次新的事件循環(huán)時會創(chuàng)建自動釋放池哩掺,事件循環(huán)(event loop)結(jié)束時凿叠,就會將其清空,所以嚼吞,一般不需要自己創(chuàng)建自動釋放池盒件。

以下兩種情況需要手動創(chuàng)建

  • main 函數(shù)中。
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

從技術(shù)角度看舱禽,不是非得有個自動釋放池塊炒刁。因為塊的末尾剛好是應(yīng)用程序的終止處,此時操作系統(tǒng)會把程序的全部內(nèi)存釋放掉誊稚。
但是翔始,如果不寫這個塊的話飒筑,那么由 UIApplication 函數(shù)所自動釋放的那些對象,就沒有自動釋放池可以容納了绽昏。系統(tǒng)也會發(fā)出警告消息來表明這一情況协屡。

  • for 循環(huán)中創(chuàng)建大量對象時
    如果 for 循環(huán)里創(chuàng)建大量臨時對象,自動釋放池要等下一次事件循環(huán)才會清空全谤。這就意味著在執(zhí)行for循環(huán)時肤晓,會持續(xù)有新對象創(chuàng)建出來,并加入釋放池中认然。所有對象要等for循環(huán)執(zhí)行完才會釋放补憾,會導(dǎo)致內(nèi)存持續(xù)上漲。
NSArray *databaseRecords = /* ... */
NSMutableArray *people = [NSMutableArray new];
        for (NSDictionary *record in databaseRecords) {
             @autoreleasepool {
                 WYJPerson *person = [WYJPerson alloc] initWithRecord: record];
                 [people addObject:person];
              }
        }

用自動釋放池將循環(huán)中的語句包起來卷员,那么循環(huán)中自動釋放的對象會放在這個池盈匾,而不是主線程的自動釋放池。這樣毕骡,每次循環(huán)時都會建立并清空釋放池削饵。

Autorelease pool 實現(xiàn)原理

Autorelease pool implementation
A thread's autorelease pool is a stack of pointers.
Each pointer is either an object to release, or POOL_BOUNDARY which is an autorelease pool boundary.
A pool token is a pointer to the POOL_BOUNDARY for that pool. When the pool is popped, every object hotter than the sentinel is released. The stack is divided into a doubly-linked list of pages. Pages are added and deleted as necessary. Thread-local storage points to the hot page, where newly autoreleased objects are stored.

上面這段是蘋果官方對 autorelease pool 實現(xiàn)的一段描述。
大概意思是:每個線程的 autorelease pool 都是一個存放指針的棧未巫。每個指針都指向一個需要釋放的對象窿撬,或者是 autorelease pool 的一個邊界。pool token 是一個指向釋放池邊界的指針叙凡。當(dāng)釋放池被彈出時劈伴,哨兵對象之后加入的對象都會被釋放。棧是由page組合成雙向鏈表握爷,需要時添加或刪除page跛璧。

AutoreleasePoolPage

void *context = objc_autoreleasePoolPush();
// {}中的代碼
objc_autoreleasePoolPop(context);

這兩個函數(shù)都是對AutoreleasePoolPage的簡單封裝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末新啼,一起剝皮案震驚了整個濱河市追城,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌师抄,老刑警劉巖漓柑,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叨吮,居然都是意外死亡辆布,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門茶鉴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來锋玲,“玉大人,你說我怎么就攤上這事涵叮〔氧澹” “怎么了伞插?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長盾碗。 經(jīng)常有香客問我媚污,道長,這世上最難降的妖魔是什么廷雅? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任耗美,我火速辦了婚禮,結(jié)果婚禮上航缀,老公的妹妹穿的比我還像新娘商架。我一直安慰自己,他們只是感情好芥玉,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布蛇摸。 她就那樣靜靜地躺著,像睡著了一般灿巧。 火紅的嫁衣襯著肌膚如雪赶袄。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天砸烦,我揣著相機與錄音弃鸦,去河邊找鬼绞吁。 笑死幢痘,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的家破。 我是一名探鬼主播颜说,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼汰聋!你這毒婦竟也來了门粪?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤烹困,失蹤者是張志新(化名)和其女友劉穎玄妈,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體髓梅,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡拟蜻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了枯饿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片酝锅。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖奢方,靈堂內(nèi)的尸體忽然破棺而出搔扁,到底是詐尸還是另有隱情爸舒,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布稿蹲,位于F島的核電站扭勉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏苛聘。R本人自食惡果不足惜剖效,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望焰盗。 院中可真熱鬧璧尸,春花似錦、人聲如沸熬拒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽澎粟。三九已至蛀序,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間活烙,已是汗流浹背徐裸。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工粗合, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留犯助,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓声怔,卻偏偏與公主長得像回懦,于是被迫代替她去往敵國和親气笙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

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