iOS記憶體管理淺析

傑瑞教育發表於2015-05-07

軟體執行時會分配和使用裝置的記憶體資源,因此,在軟體開發的過程中,需要進行記憶體管理,以保證高效、快速的分配記憶體,並且在適當的時候釋放和回收記憶體資源。

一、Objective-C記憶體管理的物件

IOS開發中,記憶體中的物件主要有兩類,一類是值型別,比如int、float、struct等基本資料型別,另一類是引用型別,也就是繼承自NSObject類的所有的OC物件。前一種值型別不需要我們管理,後一種引用型別是需要我們管理記憶體的,一旦管理不好,就會產生非常糟糕的後果。

為什麼值型別不需要管理,而引用型別需要管理呢?那是因為他們分配記憶體方式不一樣。

值型別會被放入棧中,他們依次緊密排列,在記憶體中佔有一塊連續的記憶體空間,遵循先進後出的原則。引用型別會被放到堆中,當給物件分配記憶體空間時,會隨機的從記憶體當中開闢空間,物件與物件之間可能會留有不確定大小的空白空間,因此會產生很多記憶體碎片,需要我們管理。

棧記憶體與堆記憶體從效能上比較,棧記憶體要優於堆記憶體,這是因為棧遵循先進後出的原則,因此當資料量過大時,存入棧會明顯的降低效能。因此,我們會把大量的資料存入堆中,然後棧中存放堆的地址,當需要呼叫資料時,就可以快速的通過棧內的地址找到堆中的資料。

值型別和引用型別之間是可以相互轉化的,把值型別轉化為引用型別的過程叫做裝箱,比如把int包裝為NSNumber,這個過程會增加程式的執行時間,降低效能。而把引用型別轉為值型別的過程叫做拆箱,比如把NSNumer轉為float,在拆箱的過程中,我們一定要注意資料原有的型別,如果型別錯誤,可能導致拆箱失敗,因此會存在安全性的問題。手動的拆箱和裝箱,都會增加程式的執行時間,降低程式碼可讀性,影響效能。

在IOS開發過程中,棧記憶體中的值型別系統會自動管理,堆記憶體中的引用型別是需要我們管理的。每個OC物件內部都專門有四個位元組來儲存引用計數器,它是一個整數,表示物件被引用的次數,通過它可以判斷物件是否被回收,如果引用計數為0,物件回收,不為0不回收。當物件執行alloc、new或者retain時,引用計數加1,release時,引用計數減1。

二、Objective-C管理記憶體的方式

Objective-c中提供了兩種記憶體管理機制MRC(Mannul Reference Counting)和ARC(Automatic Reference Counting),分別提供對記憶體的手動和自動管理,來滿足不同的需求。MRC與ARC區別如下圖所示。

IOS 記憶體管理

1.MRC(人工引用計數),手動管理記憶體。

MRC模式下,所有的物件都需要手動的新增retain、release程式碼來管理記憶體。使用MRC,需要遵守誰建立,誰回收的原則。也就是誰alloc,誰release;誰retain,誰release。

當引用計數為0的時候,必須回收,引用計數不為0,不能回收,如果引用計數為0,但是沒有回收,會造成記憶體洩露。如果引用計數為0,繼續釋放,會造成野指標。為了避免出現野指標,我們在釋放的時候,會先讓指標=nil。

2.ARC(自動引用計數),自動管理記憶體。

ARC是IOS5推出的新功能,通過ARC,可以自動的管理記憶體。在ARC模式下,只要沒有強指標(強引用)指向物件,物件就會被釋放。在ARC模式下,不允許使用retain、release、retainCount等方法。並且,如果使用dealloc方法時,不允許呼叫[super dealloc]方法。

ARC模式下的property變數修飾詞為strong、weak,相當於MRC模式下的retain、assign。strong :代替retain,預設關鍵詞,代表強引用。weak:代替assign,宣告瞭一個可以自動設定nil的弱引用,但是比assign多一個功能,指標指向的地址被釋放之後,指標本身也會自動被釋放。

三、與記憶體有關的修飾符

strong :強引用,ARC中使用,與MRC中retain類似,使用之後,計數器+1。

weak :弱引用 ,ARC中使用,如果只想的物件被釋放了,其指向nil,可以有效的避免野指標,其引用計數為1。

readwrite : 可讀可寫特性,需要生成getter方法和setter方法時使用。

readonly : 只讀特性,只會生成getter方法 不會生成setter方法,不希望屬性在類外改變。

assign :賦值特性,不涉及引用計數,弱引用,setter方法將傳入引數賦值給例項變數,僅設定變數時使用。

retain :表示持有特性,setter方法將傳入引數先保留,再賦值,傳入引數的retaincount會+1。

copy :表示拷貝特性,setter方法將傳入物件複製一份,需要完全一份新的變數時。

nonatomic :非原子操作,不加同步,多執行緒訪問可提高效能,但是執行緒不安全的。決定編譯器生成的setter getter是否是原子操作。

atomic :原子操作,同步的,表示多執行緒安全,與nonatomic相反。

四、MRC與ARC混編

MRC與ARC理論上是不能相容的,也就是你如果建立的專案是ARC模式的,在你的程式碼中是不能使用release,否則會出現記憶體問題。現在大部分程式都會選擇ARC的方式,但是很多第三方的框架是MRC模式,如果想把這些第三方的檔案加到自己專案中,需要進行標識,否則編譯的時候會出現錯誤。

在ARC的專案中,對MRC的檔案可以新增編譯選項-fno-objc-arc的標識;在MRC的專案中,對ARC的檔案可以新增編譯選項 -fobjc-arc的標識。 步驟如下圖所示。

IOS 記憶體管理

把MRC檔案轉為ARC,實際上是去掉檔案中的retain、release,因此也通過下圖中方式完成。

IOS 記憶體管理

相關文章