Objective-C教學
Objective-C 教學首頁
Objective-C 語言概述
Objective-C 開發環境(安裝配置)
Objective-C語言程序結構
Objective-C 基本語法
Objective-C 數據類型
Objective-C 變量
Objective-C 常量
Objective-C 運算符
Objective-C 算術運算符
Objective-C 關係運算符
Objective-C 邏輯運算符
Objective-C 位運算符
Objective-C 賦值運算符
Objective-C 循環
Objective-C while循環
Objective-C for循環
Objective-C do...while循環
Objective-C 嵌套循環
Objective-C break語句
Objective-C continue語句
Objective-C 決策
Objective-C if語句
Objective-C if...else 語句
Objective-C 嵌套 if 語句
Objective-C switch語句
Objective-C 嵌套switch語句
Objective-C 函數
Objective-C 函數按值調用
Objective-C 函數引用調用
Objective-C 塊
Objective-C Numbers/數字
Objective-C Arrays/數組
Objective-C 多維數組
Objective-C 數組作爲函數參數傳遞
Objective-C 從函數返回數組
Objective-C 指針的數組
Objective-C 指針
Objective-C 指針運算
Objective-C 數組的指針
Objective-C 指向指針的指針
Objective-C 傳遞函數的指針
Objective-C 函數返回指針
Objective-C NSString/字符串
Objective-C struct/結構
Objective-C 預處理器
Objective-C typedef
Objective-C 類型轉換
Objective-C 日誌處理
Objective-C 錯誤處理
命令行參數
Objective-C 類&對象
Objective-C 繼承
Objective-C 多態性
Objective-C 數據封裝
Objective-C Categories/類別
Objective-C Posing/冒充
Objective-C 擴展
Objective-C Protocols/協議
Objective-C 動態綁定
Objective-C 複合對象
Obj-C Foundation/基礎框架
Objective-C 數據存儲
Objective C 文本和字符串
Objective-C 日期和時間
Objective-C 異常處理
Objective-C 文件處理
Objective-C URL加載系統
Objective-C 快速枚舉
Objective-C 內存管理

Objective-C 內存管理

內存管理是任何編程語言中最重要的過程之一。它是一個過程,通過該對象的內存時,需要時分配,當不再需要時釋放。

管理對象的內存性能是一個問題,如果一個應用程序沒有免費的不需要的對象,其內存佔用量的增長和性能將受到影響。

Objective-C的內存管理技術大致可分爲兩類。

  • 「手動保留釋放」或MRR

  • 「自動引用計數」或ARC

「手動保留釋放」或MRR

在 MRR中,我們明確地管理內存,在我們自己的跟蹤對象。這是使用一種模式,被稱爲引用計數,基礎類NSObject 提供配合運行環境。

MRR 和 ARC 之間的唯一區別是,保留和釋放處理前手動而隨後自動處理。

下圖表示如何在Objective-C 內存管理工作的一個例子。

Objective-C

在上圖中所示的A類對象的存儲生命週期。正如可以看到,如下圖所示的對象保留計數,當保留計數的對象變爲0的,對象是完全釋放,其它對象使用的內存被釋放。

A類對象第一次被創建,使用分配/ NSObject的init方法。現在,保留計數變爲1。

現在,B類保留A類的對象和保留計數類A的對象變成2。

然後,C類對象的一個副本。現在,它被創建爲A類的實例變量的值相同的另一個實例。在這裏,保留計數爲1,而不是原來的對象的保留計數。這在圖中由虛線表示。

複製的對象將釋放C類使用釋放方法,並保留計數變爲0,因此對象被銷燬。

在初始A類對象的情況下,保留計數爲2,它有兩次被釋放,以便將其銷燬。這是通過類A和B類保留計數遞減爲1和0,分別使用 release 語句。最後,對象將被破壞。

MRR基本規則

  • 我們擁有我們所創建的任何對象:我們創建了一個對象,使用方法的名字以 "alloc", "new", "copy" 或 "mutableCopy"開始

  • 我們可以把一個對象使用保留所有權:接收到的對象通常是保證在收到它的方法仍然有效,並且該方法也可以安全地返回其調用對象。我們使用保留在兩種情況下:

    • 在執行存取方法或者一個init方法,採取所有權,我們要存儲一個對象的屬性值。

    • 爲了防止一個對象被無效的一些其他的操作的一個副作用。

  • 當我們不再需要它,我們必須放棄所有權的對象,我們自己:我們放棄對象的所有權,通過發送一個釋放消息或一個自動釋放的消息。在可可術語,放棄一個對象的所有權,因此通常被稱爲「釋放」一個對象。

  • 不能放棄擁有一個對象(不屬於自己):這只是推論明確說明以前的策略規則。

#import <Foundation/Foundation.h> @interface SampleClass:NSObject - (void)sampleMethod; @end @implementation SampleClass - (void)sampleMethod { NSLog(@"Hello, World!
"); } - (void)dealloc { NSLog(@"Object deallocated"); [super dealloc]; } @end int main() { /* my first program in Objective-C */ SampleClass *sampleClass = [[SampleClass alloc]init]; [sampleClass sampleMethod]; NSLog(@"Retain Count after initial allocation: %d", [sampleClass retainCount]); [sampleClass retain]; NSLog(@"Retain Count after retain: %d", [sampleClass retainCount]); [sampleClass release]; NSLog(@"Retain Count after release: %d", [sampleClass retainCount]); [sampleClass release]; NSLog(@"SampleClass dealloc will be called before this"); // Should set the object to nil sampleClass = nil; return 0; }

當我們編譯上面的程序,我們會得到下面的輸出。

2013-09-28 04:39:52.310 demo[8385] Hello, World!
2013-09-28 04:39:52.311 demo[8385] Retain Count after initial allocation: 1
2013-09-28 04:39:52.311 demo[8385] Retain Count after retain: 2
2013-09-28 04:39:52.311 demo[8385] Retain Count after release: 1
2013-09-28 04:39:52.311 demo[8385] Object deallocated
2013-09-28 04:39:52.311 demo[8385] SampleClass dealloc will be called before this

「自動引用計數」或ARC

在自動引用計數或ARC時,系統使用相同的引用計數系統MRR,但它插入相應的內存管理方法要求我們在編譯時間。我們強烈鼓勵使用ARC新的項目中。如果我們使用ARC,通常是有沒有需要了解本文檔中描述的底層實現,儘管它可能在某些情況下是有益的。如需更多關於ARC,請參閱 過渡到ARC發佈註釋.

正如上面所提到的,在ARC中我們需要不加釋放和保留的方法,因爲這將得到編譯器的處理。事實上,底層的 Objective-C 程序仍然是一樣的。它使用的保留和釋放內部的操作使它更容易爲開發人員代碼不擔心這些操作的情況下,這將減少代碼編寫量和內存泄漏的可能性。

還有另一個稱爲垃圾收集的原則,這是用來在Mac OS-X以及MRR,但其在OS-XMountain Lion 中棄用以來,它已經不隨着MRR討論。此外,iOS 的對象從未有過的垃圾收集特點。較ARC,在OS-X是沒有用垃圾收集。

下面是一個簡單的ARC例子

#import <Foundation/Foundation.h> @interface SampleClass:NSObject - (void)sampleMethod; @end @implementation SampleClass - (void)sampleMethod { NSLog(@"Hello, World!
"); } - (void)dealloc { NSLog(@"Object deallocated"); } @end int main() { /* my first program in Objective-C */ @autoreleasepool{ SampleClass *sampleClass = [[SampleClass alloc]init]; [sampleClass sampleMethod]; sampleClass = nil; } return 0; }

當我們編譯上面的程序,我們會得到下面的輸出。

2013-09-28 04:45:47.310 demo[8385] Hello, World!
2013-09-28 04:45:47.311 demo[8385] Object deallocated