iOS記憶體管理淺析
軟體執行時會分配和使用裝置的記憶體資源,因此,在軟體開發的過程中,需要進行記憶體管理,以保證高效、快速的分配記憶體,並且在適當的時候釋放和回收記憶體資源。
一、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區別如下圖所示。
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的標識。 步驟如下圖所示。
把MRC檔案轉為ARC,實際上是去掉檔案中的retain、release,因此也通過下圖中方式完成。
相關文章
- 淺析java記憶體管理機制Java記憶體
- 淺析虛擬機器記憶體管理模型虛擬機記憶體模型
- 淺析Linux Kernel[5.11.0]記憶體管理(一)Linux記憶體
- 【Java】 記憶體分配全面淺析Java記憶體
- Java 記憶體模型 JMM 淺析Java記憶體模型
- 淺析JVM記憶體分割槽JVM記憶體
- iOS記憶體淺談iOS記憶體
- 淺析C#程式設計中的記憶體管理C#程式設計記憶體
- iOS 記憶體管理iOS記憶體
- Java中字串記憶體位置淺析Java字串記憶體
- “理解”iOS記憶體管理iOS記憶體
- iOS 記憶體管理MRCiOS記憶體
- iOS 記憶體管理研究iOS記憶體
- iOS arc 記憶體管理iOS記憶體
- Netty 中的記憶體分配淺析Netty記憶體
- Linux 記憶體池原始碼淺析Linux記憶體原始碼
- iOS記憶體管理詳解iOS記憶體
- iOS 中的記憶體管理iOS記憶體
- iOS記憶體管理相關iOS記憶體
- 理解 iOS 的記憶體管理iOS記憶體
- Linux作業系統記憶體淺析Linux作業系統記憶體
- android防止記憶體溢位淺析(一)Android記憶體溢位
- android防止記憶體溢位淺析(二)Android記憶體溢位
- iOS 進階—— iOS 記憶體管理 & BlockiOS記憶體BloC
- iOS內功篇:記憶體管理iOS記憶體
- iOSARC記憶體管理要點iOS記憶體
- iOS另類的記憶體管理iOS記憶體
- MJiOS底層筆記--記憶體管理iOS筆記記憶體
- iOS開發筆記(一):記憶體管理iOS筆記記憶體
- 記憶體管理 記憶體管理概述記憶體
- Netty 中的記憶體分配淺析-資料容器Netty記憶體
- Java程式設計技術之淺析JVM記憶體Java程式設計JVM記憶體
- 淺析香港伺服器記憶體過高的原因伺服器記憶體
- 淺析JVM記憶體結構和6大區域JVM記憶體
- iOS Block淺淺析iOSBloC
- iOS 記憶體管理相關面試題iOS記憶體面試題
- 理解 iOS 和 macOS 的記憶體管理iOSMac記憶體
- 說說iOS與記憶體管理(上)iOS記憶體