oc009---內存管理原則

  1. 誰創建,誰release
    ➢ 如果你通過alloc、new或[mutable]copy來創建一個對象,那麼你必須調用release或autorelease
    ➢ 換句話說,不是你創建的,就不用你去[auto]release

  2. 誰retain,誰release
    ➢ 只要你調用了retain,無論這個對象是如何生成的,你都要調用release

  3. 總結
    ➢ 有始有終,有加就有減
    ➢ 曾經讓對象的計數器+1,就必須在最後讓對象計數器-1

set方法的內存管理

如果你有個OC對象類型的成員變量,就必須管理這個成員變量的內存。比如有個Book *_book
1. set方法的實現
- (void)setBook:(Book *)book{
if (book != _book) {
[_book release];
_book = [book retain];
}
}

  1. dealloc方法的實現
    • (void)dealloc {
      [_book release];
      [super dealloc];
      }

@property參數

  1. 控制set方法的內存管理
    ➢ retain : release舊值,retain新值(用於OC對象)
    ➢ assign : 直接賦值,不做任何內存管理(默認,用於非OC對象類型)
    ➢ copy : release舊值,copy新值(一般用於NSString *)

  2. 控制需不需生成set方法
    ➢ readwrite :同時生成set方法和get方法(默認)
    ➢ readonly :只會生成get方法

  3. 多線程管理
    ➢ atomic :性能低(默認)
    ➢ nonatomic :性能高

  4. 控制set方法和get方法的名稱
    ➢ setter : 設置set方法的名稱,一定有個冒號:
    ➢ getter : 設置get方法的名稱

循環引用

  1. @class
    ➢ 使用場景
    對於循環依賴關係來說,比方A類引用B類,同時B類也引用A類

這種代碼編譯會報錯。當使用@class在兩個類相互聲明,就不會出現編譯報錯
➢ 用法概括
使用 @class 類名; 就可以引用一個類,說明一下它是一個類
➢ 和#import的區別
 #import方式會包含被引用類的所有信息,包括被引用類的變量和方法;@class方式只是告訴編譯器在A.h文件中 B *b 只是類的聲明,具體這個類裏有什麼信息,這裏不需要知道,等實現文件中真正要用到時,纔會真正去查看B類中信息
 如果有上百個頭文件都#import了同一個文件,或者這些文件依次被#improt,那麼一旦最開始的頭文件稍有改動,後面引用到這個文件的所有類都需要重新編譯一遍,這樣的效率也是可想而知的,而相對來 講,使用@class方式就不會出現這種問題了
 在.m實現文件中,如果需要引用到被引用類的實體變量或者方法時,還需要使用#import方式引入被引用類

  1. 循環retain
    ➢ 比如A對象retain了B對象,B對象retain了A對象
    ➢ 這樣會導致A對象和B對象永遠無法釋放

  2. 解決方案
    ➢ 當兩端互相引用時,應該一端用retain、一端用assign

autorelease

  1. autorelease
    ➢ 給某個對象發送一條autorelease消息時,就會將這個對象加到一個自動釋放池中
    ➢ 當自動釋放池銷燬時,會給池子裏面的所有對象發送一條release消息
    ➢ 調用autorelease方法時並不會改變對象的計數器,並且會返回對象本身
    ➢ autorelease實際上只是把對release的調用延遲了,對於每一次autorelease,系統只是把該對象放入了當前的autorelease pool中,當該pool被釋放時,該pool中的所有對象會被調用Release

  2. 自動釋放池的創建
    ➢ ios 5.0後
    @autoreleasepool
    {
    // ….
    }
    ➢ ios 5.0前
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    // …..
    [pool release]; // 或[pool drain];
    ➢ 在程序運行過程中,可以創建多個自動釋放池,它們是以棧的形式存在內存中
    ➢ OC對象只需要發送一條autorelease消息,就會把這個對象添加到最近的自動釋放池中(棧頂的釋放池)

  3. 應用實例
    ➢ 跟release的對比
     以前:


Book *book = [[Book alloc] init];
[book release];

 現在:
Book *book = [[[Book alloc] init] autorelease];
// 不要再調用[book release];

➢ 一般可以爲類添加一個快速創建對象的類方法
+ (id)book {
return [[[Book alloc] init] autorelease];
}
外界調用[Book book]時,根本不用考慮在什麼時候釋放返回的Book對象

  1. 規律
    ➢ 一般來說,除了alloc、new或copy之外的方法創建的對象都被聲明瞭autorelease
    ➢ 比如下面的對象都已經是autorelease的,不需要再release
NSNumber *n = [NSNumber numberWithInt:100];
NSString *s = [NSString stringWithFormat:@"jack"];
NSString *s2 = @"rose";
發佈了53 篇原創文章 · 獲贊 3 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章