淺談iOS內(nèi)存管理

作為一個(gè)iOS開發(fā)者,了解iOS的內(nèi)存管理是必不可少的。

iOS采取的內(nèi)存管理策略

iOS沒有垃圾回收機(jī)制,采用了RC(Reference Counting)引用計(jì)數(shù)的方式來管理對(duì)象的生命周期席爽。如下圖(出處蘋果官方文檔):

ARC.png

在iOS系統(tǒng)里面,每個(gè)對(duì)象都有著一個(gè)與之關(guān)聯(lián)的計(jì)數(shù)啊片。當(dāng)使用alloc,new方法或者通過copy消息創(chuàng)建對(duì)象的時(shí)候只锻,對(duì)象計(jì)數(shù)器的值設(shè)置為1。當(dāng)對(duì)象調(diào)用retain方法紫谷,該對(duì)象的保留計(jì)數(shù)增加1齐饮,反之,如果對(duì)象調(diào)用release方法笤昨,該對(duì)象的保留計(jì)數(shù)減少1(注意:如果對(duì)象本身的保留計(jì)數(shù)為0祖驱,再調(diào)用或者說發(fā)送release消息就會(huì)造成crash)。當(dāng)一個(gè)對(duì)象的計(jì)數(shù)為0時(shí)咬腋,系統(tǒng)會(huì)自動(dòng)向?qū)ο蟀l(fā)送dealloc消息羹膳,銷毀對(duì)象,釋放內(nèi)存根竿。

對(duì)象操作 Objective-C方法
生成并持有對(duì)象 alloc/new/copy/mutableCopy等
持有對(duì)象 retain
釋放對(duì)象 release
廢棄對(duì)象 dealloc
自己生成的對(duì)象陵像,自己持有
id object1 = [[NSObject alloc] init];    //生成并持有對(duì)象,retainCount = 1
id object2 = [NSObject new];    //生成并持有對(duì)象寇壳,retainCount = 1
非自己生成的對(duì)象醒颖,自己也能持有
id object = [[NSMutableArray array] autorelease];      //取得非自己生成的對(duì)象,但是不持有
[object retain];    //持有該對(duì)象
非自己生成的對(duì)象壳炎,自己也能持有是通過autorelease來實(shí)現(xiàn)的泞歉,即:
+ (id)array {
    id object = [[NSArray alloc] init];
    [object autorelease];
    return object;
}
調(diào)用alloc方法生成對(duì)象后,retainCount = 1匿辩,然后將object加入autoreleasepool腰耙,延時(shí)釋放,再返回object铲球。
object調(diào)用autorelease方法挺庞,等同于release方法,只不過不是立馬調(diào)用稼病,而是等到autoreleasepool被釋放的時(shí)候选侨,再調(diào)用release方法掖鱼。
不需要自己持有對(duì)象時(shí)釋放
id object = [[NSObject alloc] init];    //生成并持有對(duì)象,retainCount = 1
[object release];
釋放非自己持有的對(duì)象

釋放非自己持有的對(duì)象援制,會(huì)導(dǎo)致對(duì)象調(diào)用retain和release方法的次數(shù)不對(duì)等戏挡,也就是release會(huì)比retain多一次,再次釋放已經(jīng)釋放掉的對(duì)象導(dǎo)致程序崩潰晨仑。

為什么iOS使用引用計(jì)數(shù)來管理內(nèi)存褐墅?

簡(jiǎn)單來說,方便管理對(duì)象的引用寻歧,可以解決對(duì)象A從一個(gè)對(duì)象傳到另一個(gè)對(duì)象的內(nèi)存管理問題掌栅。具體可以看一下唐巧的《理解 iOS 的內(nèi)存管理》,里面會(huì)有詳細(xì)的說明码泛。

MRC和ARC

現(xiàn)在猾封,直到iOS內(nèi)存管理是采用引用計(jì)數(shù),那么噪珊?在ARC(Auto reference counting)出現(xiàn)之前晌缘,需要使用者手動(dòng)管理對(duì)象的生命周期,即在適當(dāng)?shù)奈恢谜{(diào)用retain痢站,release和autorelease磷箕。ARC的出現(xiàn),大大提高了開發(fā)者的開發(fā)效率以及調(diào)高了程序運(yùn)行的效率阵难,ARC會(huì)在某些地方優(yōu)化引用計(jì)數(shù)岳枷,比如說一個(gè)局部返回對(duì)象如果馬上賦值給一個(gè)強(qiáng)引用的對(duì)象,則局部對(duì)象不會(huì)被加進(jìn)autoreleasepool里面呜叫,提高效率等等空繁。

查看對(duì)象的引用計(jì)數(shù)?

現(xiàn)在XCode都默認(rèn)開啟ARC朱庆,如果需要查看對(duì)像的引用計(jì)數(shù)盛泡,需要設(shè)置ARC無效,如下:

MRC.png
id object = [[NSArray alloc] init];
//ARC無效
NSLog(@"retainCount: %ld", [object retainCount]);
//ARC有效
NSLog(@"retainCount: %ld", CFGetRetainCount((CFTypeRef)object));
MRC需要注意下面幾點(diǎn):

(1)使用alloc,new或copy方法創(chuàng)建對(duì)象時(shí)娱颊,該對(duì)象的保留計(jì)數(shù)為1傲诵。當(dāng)不再使用該對(duì)象時(shí),向該對(duì)象發(fā)送一條release或者autorelease消息箱硕。
(2)如果你通過其他方法獲得一個(gè)對(duì)象拴竹,則不需要你來管理該對(duì)象的生命周期,除非你想在一段時(shí)間內(nèi)擁有改對(duì)象剧罩,則需要在使用前retain殖熟,使用完成后release。
(3)必須保證retain和release成對(duì)出現(xiàn)斑响。
(4)release操作只是使當(dāng)前對(duì)象的保留計(jì)數(shù)減1菱属,并不是銷毀該對(duì)象。當(dāng)該對(duì)象的保留計(jì)數(shù)為0時(shí)舰罚,才會(huì)發(fā)送dealloc消息纽门,銷毀對(duì)象。
(5)把對(duì)象加入autoreleasepool也不是立馬使對(duì)象的保留計(jì)數(shù)減1营罢,而是autoreleasepool銷毀時(shí)同時(shí)把a(bǔ)utoreleasepool里的所有對(duì)象都調(diào)用release方法赏陵。

ARC自動(dòng)引用計(jì)數(shù)

不得不說,蘋果引入ARC是一個(gè)英明的決定饲漾,從此蝙搔,蘋果開發(fā)者告別手動(dòng)管理內(nèi)存的艱難時(shí)期,是廣大開發(fā)者的福音考传。為什么ARC那么強(qiáng)大呢吃型?其實(shí)ARC只是做了一件事,就是在編譯時(shí)自動(dòng)幫你的代碼插入retain和release僚楞。恰恰勤晚,它強(qiáng)大之處就在于這里,避免開發(fā)者忘記添加retian和release泉褐,一兩個(gè)對(duì)象不覺得的赐写,如果對(duì)象很多的話,就很容易忘記膜赃,所以說挺邀,ARC幫我們解決了手動(dòng)管理對(duì)象生命周期的痛苦,讓我們更專注于代碼的邏輯實(shí)現(xiàn)跳座。
雖然ARC很強(qiáng)大端铛,但是并不是所有的對(duì)象都能用ARC,一些不能使用ARC的對(duì)象,還是得手動(dòng)管理內(nèi)存躺坟。

可以使用ARC的對(duì)象:

(1)block
(2)Objective-C對(duì)象
(3)__attribute_((NSObject))修飾的對(duì)象

不可以使用ARC的對(duì)象

Core Function對(duì)象

ARC與autoreleasepool

ARC的作用就是在編譯時(shí)期幫代碼自動(dòng)插入retain和release沦补,而autorelease就是將需要釋放的對(duì)象加入到一個(gè)stack里面,并不會(huì)立刻釋放咪橙,而是在autorelease pool銷毀時(shí)夕膀,一齊釋放棧里面的對(duì)象。其實(shí)就是相當(dāng)于release的作用美侦。當(dāng)時(shí)产舞,不明白,既然有了ARC為什么還需要autoreleasepool菠剩?其實(shí)關(guān)鍵之處在于作用域易猫,如果的創(chuàng)建與釋放隔的很近,ARC在編譯時(shí)就很容易判斷在哪個(gè)位置插入retain和release具壮,但是如果橫跨幾個(gè)文件或者說不知道什么時(shí)候釋放該對(duì)象准颓,這時(shí)候autorelease就很有用了哈蝇,每個(gè)線程的RunLoop都有自己的autoreleasepool,當(dāng)該RunLoop結(jié)束時(shí)攘已,autoreleasepool就會(huì)被銷毀炮赦,里面所有的對(duì)象也會(huì)一一銷毀。

參考:
Advanced Memory Management Programming Guide
Objective-C 中的內(nèi)存分配
理解 iOS 的內(nèi)存管理
《Objective-C高級(jí)編程 iOS與OSX 多線程和內(nèi)存管理》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末样勃,一起剝皮案震驚了整個(gè)濱河市吠勘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌峡眶,老刑警劉巖剧防,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異辫樱,居然都是意外死亡峭拘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門搏熄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棚唆,“玉大人,你說我怎么就攤上這事心例∠瑁” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵止后,是天一觀的道長(zhǎng)瞎惫。 經(jīng)常有香客問我,道長(zhǎng)译株,這世上最難降的妖魔是什么瓜喇? 我笑而不...
    開封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮歉糜,結(jié)果婚禮上乘寒,老公的妹妹穿的比我還像新娘。我一直安慰自己匪补,他們只是感情好伞辛,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著夯缺,像睡著了一般蚤氏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上踊兜,一...
    開封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天竿滨,我揣著相機(jī)與錄音,去河邊找鬼。 笑死于游,一個(gè)胖子當(dāng)著我的面吹牛毁葱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贰剥,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼头谜,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了鸠澈?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤截驮,失蹤者是張志新(化名)和其女友劉穎笑陈,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葵袭,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涵妥,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了坡锡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蓬网。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖鹉勒,靈堂內(nèi)的尸體忽然破棺而出帆锋,到底是詐尸還是另有隱情,我是刑警寧澤禽额,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布锯厢,位于F島的核電站,受9級(jí)特大地震影響脯倒,放射性物質(zhì)發(fā)生泄漏实辑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一藻丢、第九天 我趴在偏房一處隱蔽的房頂上張望剪撬。 院中可真熱鬧,春花似錦悠反、人聲如沸残黑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萍摊。三九已至,卻和暖如春如叼,著一層夾襖步出監(jiān)牢的瞬間冰木,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留踊沸,地道東北人歇终。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像逼龟,于是被迫代替她去往敵國(guó)和親评凝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

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

  • iOS內(nèi)存管理機(jī)制的原理是引用計(jì)數(shù)腺律,引用計(jì)數(shù)簡(jiǎn)單來說就是統(tǒng)計(jì)一塊內(nèi)存的所有權(quán)奕短,當(dāng)這塊內(nèi)存被創(chuàng)建出來的時(shí)候,它的引用...
    且行且珍惜_iOS閱讀 5,245評(píng)論 19 133
  • 內(nèi)存管理 簡(jiǎn)述OC中內(nèi)存管理機(jī)制匀钧。與retain配對(duì)使用的方法是dealloc還是release翎碑,為什么?需要與a...
    丶逐漸閱讀 1,971評(píng)論 1 16
  • 29.理解引用計(jì)數(shù) Objective-C語言使用引用計(jì)數(shù)來管理內(nèi)存之斯,也就是說日杈,每個(gè)對(duì)象都有個(gè)可以遞增或遞減的計(jì)數(shù)...
    Code_Ninja閱讀 1,493評(píng)論 1 3
  • 1.1 什么是自動(dòng)引用計(jì)數(shù) 概念:在 LLVM 編譯器中設(shè)置 ARC(Automaitc Reference Co...
    __silhouette閱讀 5,187評(píng)論 1 17
  • Cocoa內(nèi)存管理機(jī)制 (1)當(dāng)你使用new莉擒、alloc、copy方法創(chuàng)建一個(gè)對(duì)象時(shí)瘫絮,該對(duì)象的保留計(jì)數(shù)器值為1.當(dāng)...
    John_LS閱讀 2,776評(píng)論 0 6