Objective-C記憶體管理

記憶體管理是任何編程語言中最重要的過程之一。它是在需要時分配對象的記憶體並在不再需要時取消分配的過程。

管理對象記憶體是一個性能問題; 如果應用程式不釋放不需要的對象,則應用程式會因記憶體佔用增加並且性能受損。

Objective-C記憶體管理技術大致可分為兩類 -

  • “手動保留或釋放”或MRR
  • “自動參考計數”或ARC

1. “手動保留釋放”或MRR

在MRR中,通過跟蹤自己的對象來明確管理記憶體。這是使用一個稱為引用計數的模型實現的,FoundationNSObject與運行時環境一起提供。

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

下圖表示記憶體管理在Objective-C中的工作方式示例。

A類對象的記憶體生命週期如上圖所示。 如您所見,保留計數顯示在對象下方,當對象的保留計數變為0時,對象將被完全釋放,並且其記憶體將被釋放以供其他對象使用。

首先使用NSObject中提供的alloc/init方法創建A類對象。 現在,保留計數變為1
現在,B類保留了A類的對象,A類對象的保留計數變為2

然後,C類拷貝該對象的副本。它被創建為A類的另一個實例,具有相同的實例變數值。 這裏,保留計數是1而不是原始對象的保留計數。如圖中的虛線表示。

使用release方法由C類釋放複製的對象,並且保留計數變為0,因此對象被銷毀。

對於初始的A類對象,保留計數為2,所以必須釋放兩次才能銷毀它。 這是通過A類和B類的釋放語句完成的,它們將保留計數分別減少到10。 最後,對象就被銷毀了。

2. MRR基本規則

  • 擁有創建的任何對象:使用名稱以“alloc”,“new”,“copy”或“mutableCopy”開頭的方法創建對象

  • 使用retain獲取對象的所有權:通常保證接收到的對象在接收到的方法中保持有效,並且該方法也可以安全地將對象返回給它的調用者。在兩種情況下使用retain -

    • 在訪問器方法或init方法的實現中,獲取想要存儲為對象屬性值的對象的所有權。
    • 防止對象因某些其他操作的副作用而失效。
  • 當不再需要它時,必須放棄對擁有的對象的所有權:通過向對象發送釋放消息或自動釋放消息來放棄對象的所有權。 因此,在Cocoa術語中,放棄對象的所有權通常被稱為“釋放”對象。

  • 不得放棄不擁有的對象的所有權。

示例代碼

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
- (void)sampleMethod;
@end

@implementation SampleClass
- (void)sampleMethod {
   NSLog(@"Hello, World! \n");
}

- (void)dealloc  {
  NSLog(@"Object deallocated");
  [super dealloc];
}

@end

int main() {

   /* 第一個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");

   // 應該將對象設置為nil
   sampleClass = nil;
   return 0;
}

執行上面示例代碼,得到以下結果 -

2018-11-16 07:02:42.556 main[152785] Hello, World!
2018-11-16 07:02:42.558 main[152785] Retain Count after initial allocation: 1
2018-11-16 07:02:42.558 main[152785] Retain Count after retain: 2
2018-11-16 07:02:42.558 main[152785] Retain Count after release: 1
2018-11-16 07:02:42.558 main[152785] Object deallocated
2018-11-16 07:02:42.558 main[152785] SampleClass dealloc will be called before this

3. “自動參考計數”或ARC

在自動引用計數或ARC中,系統使用與MRR相同的引用計數系統,但它在編譯時為我們插入適當的記憶體管理方法調用。 強烈建議將ARC用於新專案。 如果使用ARC,通常不需要理解本文檔中描述的底層實現,儘管在某些情況下它可能會有所幫助。 有關ARC的更多資訊,請參閱ARC發行說明

如上所述,在ARC中,不需要添加releaseretain方法,因為編譯器會對此進行處理。 實際上,Objective-C的基本過程仍然是相同的。 它在內部使用保留和釋放操作,使開發人員更容易編碼而無需擔心這些操作,這將減少寫入的代碼量和記憶體洩漏的可能性。

還有另一個原則叫做垃圾收集,它在Mac OS-X中與MRR一起使用,但由於它在OS-X Mountain Lion中的棄用,它還沒有與MRR一起討論過。 此外,iOS對象從未擁有垃圾收集功能。 使用ARC,OS-X中也沒有使用垃圾收集。

這是一個簡單的ARC示例。 請注意,這不適用於線上編譯器,因為它不支持ARC。

#import <Foundation/Foundation.h>

@interface SampleClass:NSObject
- (void)sampleMethod;
@end

@implementation SampleClass
- (void)sampleMethod {
   NSLog(@"Hello, World! \n");
}

- (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;
}

執行上面示例代碼,得到以下結果 -

2018-10-28 08:45:17.210 demo[8385] Hello, World!
2018-10-28 08:45:17.211 demo[8385] Object deallocated

上一篇: Objective-C快速枚舉 下一篇:無