《Objective-C基礎教程》第9章 內存管理

第9章 內存管理

9.1 對象生命週期

9.1.1 引用計數

一個對象被從堆中分配出來之後,我們需要明確的知道是誰擁有了這個對象,因爲只有擁有這個對象的所有者能夠銷燬它。但我們在實際使用過程中, 這個對象可能被傳遞給另一個對象(例如通過傳遞指針參數),一旦這個過程複雜,我們很難確定誰最後擁有了這個對象。

使用引用計數就可以拋開這個問題,我們不需要再去關心誰擁有了這個對象,因爲我們把管理權交割給了對象自己。當這個對象不再被任何人使用時,它自己負責銷燬自己。

引用計數器(保留計數器):每個對象都有一個與之相關的整數,當某段代碼需要訪問一個對象時,該代碼就將該對象的保留計數器值加1,表示“我要訪問該對象”;反之,則減1,表示不再訪問該對象。當保留計數器值爲0時,表示不再有代碼訪問該對象,它將被銷燬。

使用alloc、new方法或通過copy消息創建一個對象時,對象保留計數器值置爲1。

-(id) retain; 計數加一,返回id類型的值,可以在接受消息同時調用retain
-(oneway void) release; 計數減一
-(NSUInteger) retainCount; 獲取計數值

保留計數器值爲0將被銷燬時,Objective-C會自動發送一條dealloc消息,可以重寫dealloc方法來釋放特殊的資源,dealloc方法會在對象銷燬時自動調用。

9.1.3 訪問方法中的保留和釋放

一種合理的訪問方法

- (void) setEngine: (Engine *) newEngine
{
    [newEngine retain];
    [engine release];
    engine = newEngine;
}

9.1.4 自動釋放

自動釋放池(autorelease pool),一個存放對象的池(集合),能夠自動釋放

NSObject類提供了一個autorelease方法:

- (id) autorelease;

該方法預設定了一條在將來某個時間發送的release消息,其返回值是接收消息的對象。當給一個對象發送autorelease消息時,實際上是將該對象添加到NSAutoreleasePool中。當自動釋放池被銷燬時,會向該池中所有對象發送release消息

示例
- (NSString *) description  
{  
    NSString * description;  
    description = [[NSString alloc] initWithFormat: @"I am %d years old", 4];  
    return([description autorelease]);  
}  
用下面的代碼調用  
NSLog(@"%@", [someObject descripion]); 
自動釋放池的創建和銷燬

自動釋放池以棧的形式實現,創建和銷燬的代價很小。

  • 通過@autoreleasepool關鍵字(推薦使用)

    使用@autorelease{}時,任何在花括號裏定義的變量在花括號外無法使用

  • 通過NSAutoreleasePool對象

    NSAutoreleasePool *pool=[NSAutoreleasePool new];

    [pool release];//釋放該池

在使用AppKit或UIKit的時候,自動釋放池會在明確的時間創建或釋放,比如在處理當前用戶事件的時候。

9.2 Cocoa的內存管理規則

  1. 當使用new、alloc或copy方法創建一個對象時,對象的保留計數器數值爲1。當不再使用該對象時,應該向該多想發送release或autorelease消息,銷燬對象
  2. 當通過其他方法獲得一個對象時,假設該對象的保留計數器的值爲1,而且已經被設置爲自動釋放,則不需要執行任何操作來確保該對象得到清理。如果打算在一段時間內擁有該對象,則需要保留它並確保在操作完成時釋放它
  3. 如果保留了某個對象,就需要(最終)釋放或自動釋放該對象。必須保持retain和release方法的使用次數相等

如果我使用了new,clloc或copy方法獲得了一個隊,則我必須釋放或自動釋放該對象。

內存管理規則

獲得途徑 臨時對象 擁有對象
alloc/new/copy 不再使用時釋放對象 在dealloc方法中釋放對象
任何其他方法 不需要執行任何操作 獲得對象時保留,在dealloc方法中釋放對象

自動釋放池被清理的時間是完全確定的:要麼是在代碼中你自己動手銷燬,要麼是使用AppKit時在事件循環結束時銷燬。

9.2.3 垃圾回收

Objective-C 2.0引入的自動內存管理機制,也稱垃圾回收。

iOS中無法使用垃圾回收的,主要原因是無法知道垃圾回收器什麼時候會起作用。

9.2.4 自動引用計數

ARC在編譯時進行工作,會在需要的地方自動插入retain和release語句,無需自己動手。

1、 有時用weak會好一些

當指針志向某個對象時,如果管理它的內存(通過retain和release),就擁有這個對象的強引用(strong reference),不管理,擁有弱引用。

保留循環(retain cycle):循環引用導致內存泄漏

弱引用和歸零弱引用可以解決這個問題

2、 一輛新車

Xcode可以將已有的項目轉換爲支持ARC的。但必須禁用垃圾回收機制。

3、 擁有者權限

爲了便於ARC工作,必須告訴編譯器哪個對象時指針的擁有者

9.3 異常

支持異常特性,需要在Xcode中啓用Enable Objective—C Exceptions項。

捕獲異常

@try{
} @catch(NSException *exception){
} @finally{
}

拋出異常

@throw theException或 [theException raise]
@try{
    NSException *e=...;
    @throw e;
} @catch(NSException *exception){
    @throw; //rethrow e.
} @finally{
}

這裏finally代碼塊會在@throw引發下一次異常處理調用前執行,@finally是在@throw發生之前調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章