軟件運行時會分配和使用設備的內存資源,因此,在軟件開發的過程中,需要進行內存管理,以保證高效、快速的分配內存,並且在適當的時候釋放和回收內存資源。
一、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區別如下圖所示。
MRC模式下,所有的對象都需要手動的添加retain、release代碼來管理內存。使用MRC,需要遵守誰創建,誰回收的原則。也就是誰alloc,誰release;誰retain,誰release。
當引用計數為0的時候,必須回收,引用計數不為0,不能回收,如果引用計數為0,但是沒有回收,會造成內存洩露。如果引用計數為0,繼續釋放,會造成野指針。為了避免出現野指針,我們在釋放的時候,會先讓指針=nil。
ARC是IOS5推出的新功能,通過ARC,可以自動的管理內存。在ARC模式下,只要沒有強指針(強引用)指向對象,對象就會被釋放。在ARC模式下,不允許使用retain、release、retainCount等方法。並且,如果使用dealloc方法時,不允許調用[super dealloc]方法。
ARC模式下的property變量修飾詞為strong、weak,相當於MRC模式下的retain、assign。strong :代替retain,缺省關鍵詞,代表強引用。weak:代替assign,聲明了一個可以自動設置nil的弱引用,但是比assign多一個功能,指針指向的地址被釋放之後,指針本身也會自動被釋放。
三、與內存有關的修飾符四、MRC與ARC混編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理論上是不能兼容的,也就是你如果創建的項目是ARC模式的,在你的代碼中是不能使用release,否則會出現內存問題。現在大部分程序都會選擇ARC的方式,但是很多第三方的框架是MRC模式,如果想把這些第三方的文件加到自己項目中,需要進行標識,否則編譯的時候會出現錯誤。
在ARC的項目中,對MRC的文件可以添加編譯選項-fno-objc-arc的標識;在MRC的項目中,對ARC的文件可以添加編譯選項 -fobjc-arc的標識。 步驟如下圖所示。
把MRC文件轉為ARC,實際上是去掉文件中的retain、release,因此也通過下圖中方式完成。