Objective-C 內存管理
內存管理是任何編程語言中最重要的過程之一。它是一個過程,通過該對象的內存時,需要時分配,當不再需要時釋放。
管理對象的內存性能是一個問題,如果一個應用程序冇有免費的不需要的對象,其內存占用量的增長和性能將受到影響。
Objective-C的內存管理技術大致可分為兩類。
-
“手動保留釋放”或MRR
-
“自動引用計數”或ARC
“手動保留釋放”或MRR
在 MRR中,我們明確地管理內存,在我們自己的跟蹤對象。這是使用一種模式,被稱為引用計數,基礎類NSObject 提供配合運行環境。
MRR 和 ARC 之間的唯一區彆是,保留和釋放處理前手動而隨後自動處理。
下圖表示如何在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