IPhone開發中的記憶體管理機制

來源:互聯網
上載者:User

我們在開發中會用到下面的這些相關知識:

copy 和 retain 的區別
    copy: 建立一個索引計數為1的對象,然後釋放舊對象
    retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數為1
    那上面的是什麼該死的意思呢?
    Copy其實是建立了一個相同的對象,而retain不是:
      比如一個NSString對象,地址為0×1111,內容為@”STR”
      Copy到另外一個NSString之後,地址為0×2222,內容相同,新的對象retain為1,舊有對象沒有變化
      retain到另外一個NSString之後,地址相同(建立一個指標,指標拷貝),內容當然相同,這個對象的retain值+1
    也就是說,retain是指標拷貝,copy是內容拷貝。哇,比想象的簡單多了…

誤釋放對象
    問題一:
      value = [array objectAtIndex:n]; //得到一個數組中的對象
      [arry removeObjectAtIndex:n]; //卸載那個對象
      因為value得到了那個對象,但是由於另外一個擁有者release了該對象,所以其實value現在成了搖擺指標(無效資料)

    問題二:
      myArray = [NSArray array];
       ...
      [myArray release];
      NSArray返回的是一個自動釋放對象,不僅myArray不應該在一段時間後release,而應該在適當的時候先retain,以防止該array被系統誤釋放。

    問題三:
      rocket = [rocketLauncher aRocket];
      [rocketLauncher release];
      和array這種資料收集類對象一樣,如果我們得到了一個類的子物件而不retain它,那麼在原父類被釋放的時候,這個rocket其實也會失去其意義。

Cocoa不同記憶體管理環境下的autorelease
    H 混合記憶體管理環境:垃圾收集法(Garbage Collection)+索引計數法(Reference Counting)
    雖然大多數情況下混合實境世界是不被推薦的,但是如果在這個情況下,autorelease需要注意以下事項:
    垃圾收集混合實境世界下:應該使用drain方法,因為release在GC模式下沒有意義
    索引計數環境下:drain和release對於autoreleasepool(自動釋放池)的效果相同

對autorelease的誤解 www.2cto.com
    A Cocoa的記憶體管理分為 索引計數法(Reference Counting/ Retain Count)和 垃圾收集法(Garbage Collection)。而iPhone上目前只支援前者,所以autorelease就成為很多人的“捷徑”。
    但是!autorelease其實並不是“自動釋放”,不像垃圾收集法,對對象之間的關係偵測後發現垃圾-刪除。但是autorelease其實是“延後釋放”,在一個運行周期後被標記為autorelease會被釋放掉。
    切記小心使用autorelease,理解autorelease,防止在你還需要該對象的時候已經被系統釋放掉了。

Interface Builder參與的記憶體管理問題
    要點:
    如果一個變數在類中被定義為了 IBOutlet 那麼你無需對其進行執行個體化,xib載入器會對其初始化。
    如果一個變數在類中被定義為了 IBOutlet 那麼你必須負責將其釋放。xib載入器不會幫忙的… …
    *切不要初始化兩回,記憶體會溢出,而且對象鎖定也會出錯。

關於索引計數(Reference Counting)的問題
    *retain值 = 索引計數(Reference Counting)
    NSArray對象會retain(retain值加一)任何數組中的對象。當NSArray被卸載(dealloc)的時候,所有數組中的對象會被執行一次釋放(retain值減一)。不僅僅是NSArray,任何收集類(Collection Classes)都執行類似操作。例如NSDictionary,甚至UINavigationController。
    Alloc/init建立的對象,索引計數為1。無需將其再次retain。
    [NSArray array]和[NSDate date]等“方法”建立一個索引計數為1的對象,但是也是一個自動釋放對象。所以是本地臨時對象,那麼無所謂了。如果是打算在全Class中使用的變數(iVar),則必須retain它。
    預設的類方法傳回值都被執行了“自動釋放”方法。(*如上中的NSArray)
    在類中的卸載方法“dealloc”中,release所有未被平衡的NS對象。(*所有未被autorelease,而retain值為1的)

NSString的記憶體管理
    如下執行個體:
      aString = @"I am a string that 2 years old, man!";
    這種情況下,字串儲存和管理由系統做,我們不用操心。
      aString = [NSString stringWithFormat:@"I am a string that %d years old, man!",2];
    第二種情況下,我們需要去retain和release這個字串,系統不管。

Objective-C記憶體管理
    1,你初始化(alloc/init)的對象,你需要釋放(release)它。例如:
      NSMutableArray aArray = [[NSArray alloc] init];
    後,需要
      [aArray release];
    2,你retain或copy的,你需要釋放它。例如:
      [aArray retain]
    後,需要
      [aArray release];
    3,被傳遞(assign)的對象,你需要斟酌的retain和release。例如:
      obj2 = [[obj1 someMethod] autorelease];
      對象2接收對象1的一個自動釋放的值,或傳遞一個基礎資料型別 (Elementary Data Type)(NSInteger,NSString)時: 你或希望將對象2進行retain,以防止它在被使用之前就被自動釋放掉。但是在retain後,一定要在適當的時候進行釋放。

為什麼不能直接調用dealloc而是release
    dealloc不等於C中的free,dealloc並不將記憶體釋放,也不會將索引計數(Reference counting)降低。於是直接調用dealloc反而無法釋放記憶體。
    在Objective-C中,索引計數是起決定性作用的。

 

摘自 白璐.中國

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.