ios內(nèi)存管理

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?ios內(nèi)存管理

一.前言

在ios中,系統(tǒng)對(duì)每個(gè)程序運(yùn)行時(shí)內(nèi)存的占有都有一個(gè)限制,默認(rèn)都是幾十兆左右,當(dāng)程序占用內(nèi)存的大小超過(guò)限制時(shí),程序可能就會(huì)被強(qiáng)制退出.

在內(nèi)存中,分為堆和棧,棧中主要存放變量,堆中主要存放對(duì)象糙捺。棧中的東西是系統(tǒng)自動(dòng)收回的,當(dāng)一個(gè)變量使用完成后,存放在棧中的東西會(huì)立即被收回恬汁。但堆中存儲(chǔ)的東西是不會(huì)被隨便回收的在岂。

由于移動(dòng)設(shè)備內(nèi)存有限,所以我們會(huì)對(duì)內(nèi)存進(jìn)行嚴(yán)格的管理,以避免內(nèi)存泄露造成資源浪費(fèi)。

在OC中,只有對(duì)象才屬于內(nèi)存管理范圍,例如int ,float,struct等基本數(shù)據(jù)類(lèi)型不存在內(nèi)存管理的概念,在ios開(kāi)發(fā)中,對(duì)內(nèi)存的管理實(shí)際上是對(duì)引用計(jì)數(shù)器的管理

相關(guān)概念:

僵尸對(duì)象:所占用的內(nèi)存被回收的對(duì)象,僵尸對(duì)象不能再使用。

野指針:指向僵尸對(duì)象的指針井濒,給野指針發(fā)消息會(huì)報(bào)錯(cuò)。

空指針:沒(méi)有指向任何東西的指針,給空指針發(fā)送消息不會(huì)報(bào)錯(cuò)列林。


目前OC內(nèi)存管理方式有三種:

(1)自動(dòng)垃圾收集(Automatic Garbage Collection)

(2)MRC(Manual Reference Counting,手動(dòng)引用計(jì)數(shù)器)和自動(dòng)釋放池(Autorelease)

(3)ARC(Automatic Reference Counting,自動(dòng)引用計(jì)數(shù)器)

自動(dòng)垃圾收集:

在OC2.0中,有一種自動(dòng)垃圾收集的內(nèi)存管理形式,通過(guò)垃圾自動(dòng)收集,系統(tǒng)能檢測(cè)出對(duì)象是否擁有其他對(duì)象,當(dāng)程序運(yùn)行期間,不被引用的對(duì)象就會(huì)被釋放瑞你。

但是在ios運(yùn)行環(huán)境中不支持自動(dòng)垃圾收集,在OS X環(huán)境才支持,不過(guò)蘋(píng)果推薦使用ARC進(jìn)行替代。

MRC和自動(dòng)釋放池子:

? 1. 引用計(jì)數(shù)器的概念:

即一個(gè)對(duì)象被引用的次數(shù),每個(gè)對(duì)象的引用計(jì)數(shù)器占4個(gè)字節(jié)希痴。

說(shuō)明當(dāng)一個(gè)對(duì)象被創(chuàng)建的時(shí)候,該對(duì)象的默認(rèn)RC為1,當(dāng)該對(duì)象被引用一次,需要調(diào)用retain方法,使RC的值加1,當(dāng)指針失去對(duì)該對(duì)象的引用,需要調(diào)用release方法,使RC的值減1者甲,當(dāng)RC的值等于0時(shí),該對(duì)象被系統(tǒng)自動(dòng)銷(xiāo)毀回收砌创。

2.對(duì)象的銷(xiāo)毀

? 當(dāng)一個(gè)對(duì)象的RC為0時(shí)虏缸,那么它將被銷(xiāo)毀,其占用的內(nèi)存會(huì)被系統(tǒng)回收.

? 當(dāng)一個(gè)對(duì)被銷(xiāo)毀時(shí),系統(tǒng)會(huì)自動(dòng)向?qū)ο蟀l(fā)送一條dealloc消息

? 一般會(huì)重寫(xiě)dealloc方法,在這里釋放相關(guān)資源,dealloc就是對(duì)象的遺言?

? 一旦重寫(xiě)了dealloc方法,就必須調(diào)用[super dealloc],并且放在最后面調(diào)用

? 對(duì)象一旦被回收了,它占用的內(nèi)存不再可用,堅(jiān)持使用就會(huì)導(dǎo)致指針錯(cuò)誤

3.MRC

通過(guò)人為的方式來(lái)控制引用計(jì)數(shù)器的增減,影響對(duì)象RC值的方式有以下幾種:

(1)new, alloc,copy,mutableCopy這幾種方式來(lái)創(chuàng)建一個(gè)新的對(duì)象,此時(shí)RC的默認(rèn)值為1.

(2)retain,對(duì)象調(diào)用retain方法,RC的值加1.

(3)release,對(duì)象調(diào)用release方法嫩实,RC的值減1.

(4)dealloc,dealloc方法并不會(huì)影響RC值,但是當(dāng)RC值為0時(shí),系統(tǒng)會(huì)調(diào)用dealloc方法來(lái)銷(xiāo)毀對(duì)象.

例如:

通過(guò)上面代碼我們知道刽辙,成員變量的設(shè)值和取值方法是手動(dòng)生成的,而且setter方法中成員變量的引用計(jì)數(shù)器也是手動(dòng)設(shè)置,我們可以通過(guò)@property和相應(yīng)關(guān)鍵字來(lái)由編譯器生成.

關(guān)于在MRC中@property關(guān)鍵字如下:

(1)assign和retain和copy

這幾個(gè)關(guān)鍵字用于setter方法的內(nèi)存管理,如果使用assign(一般用于非OC對(duì)象),那么將直接進(jìn)行賦值操作;如果使用retain(一般用于OC對(duì)象),那么將retain新值,release舊值;如果使用copy,那么將release舊值,copy新值。

(2)nonatomic和atomic

這兩個(gè)關(guān)鍵字用于多線程管理,nonatomic的性能高,atomic的性能低.不顯示則atomic為默認(rèn)值

(3)readwrite和readonly

這兩個(gè)關(guān)鍵字說(shuō)明是否生成setter方法,readwrite將自動(dòng)生成setter方法和getter方法甲献。readonly則只生成getter方法

如果使用@property屬性,上述代碼可以改為:

4.循環(huán)引用內(nèi)存管理原則

對(duì)于兩個(gè)類(lèi)B包含A,A包含B的循環(huán)引用情況下,看如下代碼:

當(dāng)執(zhí)行Book*b1=[[Book1 alloc]init]后;b1指向Book1宰缤。

當(dāng)執(zhí)行Book2*b2=[[Book2 alloc]init]后,b2指向Book2。

當(dāng)執(zhí)行b1.book2=b2后;Book1中的成員變量_book2指向Book2。

當(dāng)執(zhí)行b2.book1=b1后;Book2中的成員變量_book1指向Book1慨灭。

此時(shí)Book1的引用計(jì)數(shù)器RC=2;Book2的引用計(jì)數(shù)器RC=2朦乏。

當(dāng)執(zhí)行[b1 release]后,b1釋放對(duì)Book1的控制權(quán),此時(shí)Book1的引用計(jì)數(shù)器RC=2-1=1。

當(dāng)執(zhí)行[b2 release]后,b2釋放對(duì)Book2的控制權(quán),此時(shí)Book2的引用計(jì)數(shù)器RC=2-1=1氧骤。

那么由于仍有指針指向Book1和Book2,所以Book1和Book2不會(huì)被銷(xiāo)毀釋放,這樣就造成內(nèi)存泄露.

對(duì)于上面的情況,只需要在Book1或者Book2的任意一端使用assign,如此就能避免互相引用呻疹。

對(duì)于下面這種循環(huán)引用情況,只能使用assign。

如果@property(nonatomic,assign)id instance中的assign換成retain,也會(huì)造成內(nèi)存泄露,因?yàn)閕d為泛型筹陵。

5.Autorelease Pool的使用

顧名思義刽锤,Autorelease即自動(dòng)釋放對(duì)象,不需要我們手動(dòng)釋放。從上面的代碼中可以知道,在main函數(shù)中,創(chuàng)建對(duì)象obj后,總需要調(diào)用[obj release]方法,這樣無(wú)疑工作量變大,且對(duì)我們的工作無(wú)多大意義惶翻。為了減少這種無(wú)意義的工作姑蓝,我們可以使用Autorelease Pool。

在ios程序運(yùn)行的過(guò)程中,會(huì)創(chuàng)建無(wú)數(shù)個(gè)池子吕粗。這些池子都是以棧結(jié)構(gòu)存在(先進(jìn)后出),當(dāng)一個(gè)對(duì)象調(diào)用autorelease方法時(shí),會(huì)將這個(gè)對(duì)象放到棧頂?shù)尼尫懦亍?/p>

Autorelease Pool即自動(dòng)釋放池,在Autorelease Pool內(nèi)的對(duì)象,其release方法最終由編譯器自動(dòng)完成,而不需要手動(dòng)執(zhí)行旭愧。

autorelease的具體使用方法:

(1)生成并持有NSAutoreleasePool對(duì)象

(2)調(diào)用已分配對(duì)象的autorelease實(shí)例方法

(3)廢棄NSAutoreleasePool對(duì)象

那到底什么時(shí)候廢棄NSAutoreleasePool對(duì)象呢?

在Cocoa框架中,相當(dāng)于程序住循環(huán)的NSRunLoop或者在其他程序可運(yùn)行的地方,對(duì)NSAutoreleasePool對(duì)象進(jìn)行生成颅筋、持有、和廢棄處理输枯。如下圖:

NSAutoreleasePool對(duì)象的生命周期如下:

NSAutoreleasePool的創(chuàng)建有兩種方式:

在返回對(duì)象的方法中最好使用自動(dòng)釋放池釋放對(duì)象,由于在返回該對(duì)象之前不能釋放該對(duì)象,所以可以通過(guò)自動(dòng)釋放池來(lái)延遲該對(duì)象的釋放议泵。如:

如果在一個(gè)循環(huán)中產(chǎn)生了大量的臨時(shí)對(duì)象,可以在循環(huán)的內(nèi)部提供一個(gè)自動(dòng)釋放池在下一次迭代前來(lái)清除這些對(duì)象,以減少最大內(nèi)存占用桃熄。


6.ARC

ARC是編譯器特性,可以理解為xcode的功能先口。它主要用來(lái)幫用戶(hù)做內(nèi)存管理工作,優(yōu)化開(kāi)發(fā)流程。

特別注意的是它與java的垃圾回收機(jī)制不是同一個(gè)東西,它僅是xcode的一個(gè)功能而已瞳收。在ARC下碉京,RC由編譯器自動(dòng)管理,不需要手動(dòng)管理螟深。

ARC判斷標(biāo)準(zhǔn):

只要沒(méi)有強(qiáng)指針指向該對(duì)象谐宙,該對(duì)象就會(huì)被釋放。就算此時(shí)有弱指針指向該對(duì)象界弧,或者該對(duì)象還指向其他對(duì)象凡蜻,只要沒(méi)有強(qiáng)指針指向其,其仍舊被釋放垢箕。

ARC特點(diǎn):

(1)不允許調(diào)用release划栓、retain、retainCount

(2)@property的參數(shù)

*strong:成員變量是強(qiáng)指針(適用于OC對(duì)象)

*weak:成員變量是弱指針(適用于OC對(duì)象)

*assign:適用于非OC對(duì)象

(3)MRC下的retain改用strong

在實(shí)際項(xiàng)目中,某些文件需要用到release,retain方法,比如下載的第三方框架中如果有release方法,放在支持ARC的環(huán)境下會(huì)報(bào)錯(cuò)条获。這時(shí)我們可以設(shè)置這些文件不使用ARC忠荞,其他支持ARC環(huán)境的文件繼續(xù)使用ARC,相應(yīng)的方法是選擇項(xiàng)目的Build phases,在Compile Sources中選擇不需要ARC的文件,雙擊或回車(chē),在彈出的窗口中輸入-fno-objc-arc即可。同理可在MRC環(huán)境中使用-f-objc-arc使相關(guān)文件支持ARC.

ARC模式下,創(chuàng)建新對(duì)象通常由以下幾種關(guān)鍵字來(lái)限定。

(1)_strong(默認(rèn)值),由_strong修飾的為強(qiáng)指針,對(duì)象只要有強(qiáng)指針指向它就不會(huì)被銷(xiāo)毀,每當(dāng)一個(gè)強(qiáng)指針指向它钻洒,該對(duì)象的RC+1奋姿。

(2)_weak,由_weak修飾的為弱指針,弱指針指向的對(duì)象不會(huì)影響該對(duì)象的RC值,當(dāng)弱指針指向的對(duì)象被銷(xiāo)毀時(shí),該指針的值為nil(即該指針指向一個(gè)nil對(duì)象)。

(3)_unsafe_unretained,該類(lèi)型指針不會(huì)影響所指對(duì)象的RC值,當(dāng)其所指向的對(duì)象被銷(xiāo)毀時(shí),該指針的值不會(huì)變?yōu)閚il,仍保留原有的地址(即仍然指向已被釋放對(duì)象的地址,因此才會(huì)_unsafe)素标。

注意:ARC模式下仍能使用自動(dòng)釋放池称诗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市头遭,隨后出現(xiàn)的幾起案子寓免,更是在濱河造成了極大的恐慌,老刑警劉巖计维,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袜香,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鲫惶,警方通過(guò)查閱死者的電腦和手機(jī)蜈首,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)欠母,“玉大人欢策,你說(shuō)我怎么就攤上這事∩吞剩” “怎么了踩寇?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)六水。 經(jīng)常有香客問(wèn)我俺孙,道長(zhǎng),這世上最難降的妖魔是什么掷贾? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任睛榄,我火速辦了婚禮,結(jié)果婚禮上胯盯,老公的妹妹穿的比我還像新娘懈费。我一直安慰自己,他們只是感情好博脑,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布憎乙。 她就那樣靜靜地躺著,像睡著了一般叉趣。 火紅的嫁衣襯著肌膚如雪泞边。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,874評(píng)論 1 314
  • 那天疗杉,我揣著相機(jī)與錄音阵谚,去河邊找鬼蚕礼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛梢什,可吹牛的內(nèi)容都是我干的奠蹬。 我是一名探鬼主播,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼嗡午,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼囤躁!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起荔睹,我...
    開(kāi)封第一講書(shū)人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤狸演,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后僻他,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體宵距,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年吨拗,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了满哪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡劝篷,死狀恐怖翩瓜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情携龟,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布勘高,位于F島的核電站峡蟋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏华望。R本人自食惡果不足惜蕊蝗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赖舟。 院中可真熱鬧蓬戚,春花似錦、人聲如沸宾抓。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)石洗。三九已至幢泼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間讲衫,已是汗流浹背缕棵。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人招驴。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓篙程,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親别厘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子虱饿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361