iOS開發(fā) —— 內(nèi)存管理

一奋隶、為什么要學(xué)習(xí)內(nèi)存管理

內(nèi)存對于任何硬件及軟件的重要性不言而喻童漩,而作為硬件與用戶交流的中間體軟件荣恐,對于內(nèi)存的要求以及如何使用內(nèi)存火惊,如何合理分配內(nèi)存是至關(guān)重要的求类,而Objective C語言是C語言的超集,對于內(nèi)存以及內(nèi)存管理方面也非常重要屹耐。在iOS開發(fā)中尸疆,內(nèi)存泄露會嚴重影響用戶體驗,而蘋果的硬件設(shè)備的內(nèi)存本身內(nèi)存就不大惶岭,所以作為iOS開發(fā)人員寿弱,掌握內(nèi)存管理是非常重要的,不過從Xcode 4.2 之后蘋果公司采用ARC編譯器特性的內(nèi)存管理機制按灶,大大的減少了程序員手動對內(nèi)存的管理症革,讓程序員把注意點放在產(chǎn)品邏輯上,使得蘋果的軟件產(chǎn)品做的更加出色鸯旁。雖然現(xiàn)在做iOS開發(fā)不采用MRC來手動管理內(nèi)存噪矛,但掌握MRC的內(nèi)存管理機制對于提升開發(fā)思維以及更深了解內(nèi)存管理機制是非常有必要的。

二铺罢、多種語言的內(nèi)存管理

(1)java語言:java虛擬機及垃圾回收機制艇挨。

(2)C++語言:相關(guān)C++內(nèi)存管理 相對比較復(fù)雜,手動管理韭赘,程序員的痛點之一缩滨。

(3)Android:如果你懂java,就會更容易理解Android系統(tǒng)的內(nèi)存管理機制泉瞻。與java的垃圾回收機制類似楷怒,系統(tǒng)有一個規(guī)則來回收內(nèi)存。進行內(nèi)存調(diào)度有個閾值瓦灶,只有低于這個值系統(tǒng)才會按一個列表來關(guān)閉用戶不需要的東西鸠删。這種內(nèi)存調(diào)度管理方式有個弊端,容易造成內(nèi)存泄露贼陶,所以很多安卓手機經(jīng)常會出現(xiàn)卡機及提示內(nèi)存滿的狀況刃泡,眾多安卓用戶的痛點巧娱。

(4)Objective C 語言:ARC編譯器管理機制,程序員在使用Xcode 4.2以上版本進行軟件開發(fā)時烘贴,編譯器自動在相應(yīng)的位置進行內(nèi)存釋放禁添,不需要手動管理。

三桨踪、堆和棧

(1)棧(操作系統(tǒng)):

由操作系統(tǒng)自動分配釋放老翘,存放函數(shù)的參數(shù)值,局部變量的值等锻离。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧(先進后出)铺峭;

(2)堆(操作系統(tǒng)):

一般由程序員分配釋放,若程序員不釋放汽纠,程序結(jié)束時可能由OS回收卫键,分配方式類似于鏈表。

四虱朵、僵尸對象莉炉、野指針、空指針

1.僵尸對象

已經(jīng)被銷毀的對象(不能再使用的對象)

2.野指針

指向僵尸對象(不可用內(nèi)存)的指針

給野指針發(fā)消息會報EXC_BAD_ACCESS錯誤

3.空指針

沒有指向存儲空間的指針(里面存的是nil, 也就是0)

給空指針發(fā)消息是沒有任何反應(yīng)的

為了避免野指針錯誤的常見辦法

在對象被銷毀之后, 將指向?qū)ο蟮闹羔樧優(yōu)榭罩羔?/p>

五碴犬、Objective C語言的內(nèi)存管理

所謂內(nèi)存管理, 就是對內(nèi)存進行管理, 涉及的操作有:

(1)分配內(nèi)存 : 比如創(chuàng)建一個對象, 會增加內(nèi)存占用

(2)清除內(nèi)存 : 比如銷毀一個對象, 能減小內(nèi)存占用

內(nèi)存管理的管理范圍

(1)任何繼承了NSObject的對象

(2)對其他非對象類型無效(int絮宁、char、float服协、double绍昂、struct、enum等 )

只有OC對象才需要進行內(nèi)存管理的根本原因:

OC對象存放于堆里面

非OC對象一般放在棧里面(棧內(nèi)存會被系統(tǒng)自動回收)

六蚯涮、MRC手動管理內(nèi)存

Manual Reference Counting:(MRC)

1.引用計數(shù)器

(1)引用計數(shù)器表示有多少人正在使用這個對象治专。

(2)當(dāng)沒有任何人使用這個對象時, 系統(tǒng)才會回收這個對象, 也就是說當(dāng)對象的引用計數(shù)器為0時,對象占用的內(nèi)存就會被系統(tǒng)回收卖陵。

(3)如果對象的計數(shù)器不為0遭顶,那么在整個程序運行過程,它占用的內(nèi)存就不可能被回收(除非整個程序已經(jīng)退出 )

(4)任何一個對象, 剛生下來的時候, 引用計數(shù)器都為1

(5)當(dāng)使用alloc泪蔫、new或者copy(MutableCopy)創(chuàng)建一個對象時棒旗,對象的引用計數(shù)器默認就是1

2.引用計數(shù)器的操作

(1)給對象發(fā)送一條retain消息,可以使引用計數(shù)器值+1(retain方法返回對象本身)

(2)給對象發(fā)送一條release消息, 可以使引用計數(shù)器值-1

(3)給對象發(fā)送retainCount消息, 可以獲得當(dāng)前的引用計數(shù)器值(retainCount有時候會不準確,建議采用delloc方法來驗證是否完全內(nèi)存釋放)

注意: release并不代表銷毀\回收對象, 僅僅是計數(shù)器-1

3.dealloc方法

(1)當(dāng)一個對象的引用計數(shù)器值為0時,這個對象即將被銷毀撩荣,其占用的內(nèi)存被系統(tǒng)回收铣揉。

(2)對象即將被銷毀時系統(tǒng)會自動給對象發(fā)送一條dealloc消息 (因此, 從dealloc方法有沒有被調(diào)用,就可以判斷出對象是否被銷毀)

dealloc方法的重寫

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

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

-(void)delloc{

[super delloc];

}

4.使用注意

不能直接調(diào)用dealloc方法

一旦對象被回收了, 它占用的內(nèi)存就不再可用,堅持使用會導(dǎo)致程序崩潰(野指針錯誤).

5.內(nèi)存管理規(guī)則

(1)誰創(chuàng)建誰release :

如果你通過alloc、new或[mutable]copy來創(chuàng)建一個對象餐曹,那么你必須調(diào)用release或autorelease

誰retain誰release:

(2)只要你調(diào)用了retain逛拱,就必須調(diào)用一次release

總結(jié):

有加就有減

曾經(jīng)讓對象的計數(shù)器+1,就必須在最后讓對象計數(shù)器-1台猴,最后重寫delloc方法來檢查內(nèi)存是否完全釋放朽合。

6.多對象內(nèi)存管理

(1)多對象內(nèi)存管理規(guī)則:

只要還有人在用某個對象俱两,那么這個對象就不會被回收

只要你想用這個對象,就讓對象的計數(shù)器+1

當(dāng)你不再使用這個對象時曹步,就讓對象的計數(shù)器-1

(2)setter方法內(nèi)存管理規(guī)則:

retain需要使用的對象

release之前的對象

只有傳入的對象和之前的不同才需要release和retain

- (void)setRoom:(Room *)room

{

// 避免過度釋放(判斷私有成員和局部成員是否相等)

if (room != _room)

{

// 對當(dāng)前正在使用的車(舊車)做一次release

[_room release]宪彩;

// _room = nil;

// 對新車做一次retain操作

_room = [room retain];

}

}

3.dealloc方法的內(nèi)存管理規(guī)則

- (void)dealloc

{

// 當(dāng)人不在了,代表不用房間了

// 對房間做一次release操作

[_room release];

// 這樣寫逼格高一點? self.room = nil;

[super dealloc];

}

7.@property參數(shù)

這里寫圖片描述

(1)控制set方法的內(nèi)存管理

retain : release舊值讲婚,retain新值(用于OC對象)

assign : 直接賦值尿孔,不做任何內(nèi)存管理(默認,用于非OC對象類型)

copy : release舊值筹麸,copy新值(一般用于NSString *)

(2)控制需不需要生成set方法

readwrite :同時生成set方法和get方法(默認)

readonly :只會生成get方法

(3)多線程管理

atomic :性能低(默認)

nonatomic :性能高(iOS開發(fā)中都用這個屬性)

(4)控制set方法和get方法的名稱

setter : 設(shè)置set方法的名稱活合,一定有個冒號:

getter : 設(shè)置get方法的名稱

若有bool類型時最好修改getter方法為:(getter = isXXX)

注意: 不同類型的參數(shù)可以組合在一起使用

(5)循環(huán)引用

當(dāng)使用@property屬性聲明兩個對象時,如果同時使用retain竹捉,會到時相互引用芜辕,內(nèi)存不會釋放,解決辦法是块差,一個用retain侵续,一個用assign。

8.autoreleasepool 自動釋放池

(1)在iOS程序運行過程中憨闰,會創(chuàng)建無數(shù)個池子状蜗。這些池子都是以棧結(jié)構(gòu)存在(先進后出),當(dāng)一個對象調(diào)用autorelease方法時鹉动,會將這個對象放到棧頂?shù)尼尫懦亍?/p>

(2)autorelease是一種支持引用計數(shù)的內(nèi)存管理方式,只要給對象發(fā)送一條autorelease消息,會將對象放到一個自動釋放池中,當(dāng)自動釋放池被銷毀時轧坎,會對池子里面的所有對象做一次release操作

注意

這里只是發(fā)送release消息,如果當(dāng)時的引用計數(shù)(reference-counted)依然不為0,則該對象依然不會被釋放。

(3)autorelease使用注意事項

并不是放到自動釋放池代碼中,都會自動加入到自動釋放池

在自動釋放池的外部發(fā)送autorelease 不會被加入到自動釋放池中

autorelease是一個方法,只有在自動釋 放池中調(diào)用才有效泽示。

如果寫了autorelease就不要寫release

只要在自動釋放池中調(diào)用autorelease, 就會將對象放入自動釋放池

自動釋放池中不適宜放占用內(nèi)存比較大的對象

不要連續(xù)調(diào)用autorelease,同時也不要把大量循環(huán)操作放到同一個 @autoreleasepool 之間

@autoreleasepool {

// 創(chuàng)建對象時用autorelease

Person *p? =[ [Person alloc]init]autorelease];

}

// 類方法

+(instancetype)person{

return [[self alloc]init]autorelease];

}

// 類工廠方法

+(instancetype)personWithAge:(int)age

{

return [[[self alloc] initWithAge:age] autorelease];

}

-(void)dealloc

{

NSLog(@"%s", __func__);

[super dealloc];

}

七缸血、ARC 自動引用計數(shù)管理內(nèi)存

Automatic Reference Counting:(ARC)

自動引用計數(shù),即ARC,可以說是WWDC2011和iOS5所引入 的最大的變革和最激動人心的變化。ARC是新的LLVM 3.0編譯器的一項特性,使用ARC,可以說一 舉解決了廣大iOS開發(fā)者所憎恨的手動內(nèi)存管理的麻煩械筛。

1.ARC機制判斷注意點及優(yōu)點

ARC機制判斷捎泻,ARC機制下有幾個明顯的標志:

不允許調(diào)用對象的release方法

再重寫父類的dealloc方法時,不能再調(diào)用 [super dealloc];

ARC的注意點

- ARC是編譯器特性,而不是運行時特性

- ARC不是其它語言中的垃圾回收,有著本質(zhì)區(qū)別ARC的

優(yōu)點

- 完全消除了手動管理內(nèi)存的煩瑣

- 基本上能夠避免內(nèi)存泄露有時還能更加快速埋哟,因為編譯器還可以執(zhí)行某些優(yōu)化

2.強指針笆豁,弱指針

強指針

默認所有指針變量都是強指針

被__strong修飾的指針

Person *p1 = [[Person alloc] init];

__strong? Person *p2 = [[Person alloc] init];


弱指針

被__weak修飾的指針

__weak? Person *p = [[Person alloc] init];

3.ARC下單對象內(nèi)存管理

(1)局部變量釋放對象隨之被釋放

(2)清空指針對象隨之被釋放

(3)默認清空所有指針都是強指針

弱指針需要明確說明 :

注意: 千萬不要使用弱指針保存新創(chuàng)建的對象

4.ARC下循環(huán)引用問題

與MRC一樣,當(dāng)兩個對象相互引用時赤赊,會出現(xiàn)內(nèi)存泄露的問題闯狱,解決辦法是:一個用strong一個用weak。

5.ARC下@property參數(shù)

strong: 用于OC對象, 相當(dāng)于MRC中的retain

weak: 用于OC對象, 相當(dāng)于MRC中的assign

assign: 用于基本數(shù)據(jù)類型, 跟MRC中的assign一樣(默認值)

6.如何將MRC轉(zhuǎn)換為ARC

在Xcode4.2 之前采用的時MRC內(nèi)存管理機制抛计,所以遇到MRC項目時可以采用Xcode里的小工具進行轉(zhuǎn)換ARC哄孤,但是不敢保證百分之百成功,所以操作需謹慎吹截。

如何進行ARC和MRC的混合使用:

轉(zhuǎn)變?yōu)榉茿RC -fno-objc-arc

轉(zhuǎn)變?yōu)锳RC的, -f-objc-arc (不常用)

如何這篇文章對您有幫助并且想與我 溝通學(xué)習(xí)和交流瘦陈,我將無償將自己整理的400GiOS學(xué)習(xí)資料進行分享朦肘。新浪微博關(guān)注?私信 ?極客James ? CSDN技術(shù)博客:http://my.csdn.net/zc639143029

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市双饥,隨后出現(xiàn)的幾起案子媒抠,更是在濱河造成了極大的恐慌,老刑警劉巖咏花,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件趴生,死亡現(xiàn)場離奇詭異,居然都是意外死亡昏翰,警方通過查閱死者的電腦和手機苍匆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棚菊,“玉大人浸踩,你說我怎么就攤上這事⊥城螅” “怎么了检碗?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長码邻。 經(jīng)常有香客問我折剃,道長,這世上最難降的妖魔是什么像屋? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任怕犁,我火速辦了婚禮,結(jié)果婚禮上己莺,老公的妹妹穿的比我還像新娘奏甫。我一直安慰自己,他們只是感情好凌受,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布阵子。 她就那樣靜靜地躺著,像睡著了一般胁艰。 火紅的嫁衣襯著肌膚如雪款筑。 梳的紋絲不亂的頭發(fā)上智蝠,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天腾么,我揣著相機與錄音,去河邊找鬼杈湾。 笑死解虱,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的漆撞。 我是一名探鬼主播殴泰,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼于宙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了悍汛?” 一聲冷哼從身側(cè)響起捞魁,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎离咐,沒想到半個月后谱俭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡宵蛀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年昆著,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片术陶。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡凑懂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出梧宫,到底是詐尸還是另有隱情接谨,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布塘匣,位于F島的核電站疤坝,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏馆铁。R本人自食惡果不足惜跑揉,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望埠巨。 院中可真熱鬧历谍,春花似錦、人聲如沸辣垒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勋桶。三九已至脱衙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間例驹,已是汗流浹背捐韩。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留鹃锈,地道東北人荤胁。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像屎债,于是被迫代替她去往敵國和親仅政。 傳聞我的和親對象是個殘疾皇子垢油,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

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