1. 程式人生 > >[Objective-C]記憶體洩漏是新手必然要經歷的痛,NSMutableArray的正確使用

[Objective-C]記憶體洩漏是新手必然要經歷的痛,NSMutableArray的正確使用

Objective-C程式開發中的記憶體洩漏問題是新手非常頭痛的事情,可能是用C#這類自動垃圾釋放的語言太習慣了,用xcode中的profile工具查了一下我寫的小程式,記憶體洩漏了一大堆,經過一陣子排查,在NSMutableArray中新增物件後不正確維護物件的引用計數是一個主要原因。

在NSMutableArray how to properly addObjects and release這個討論主題中,給出了正確的使用NSMutableArray的步驟,先看他給出的程式碼。

NSMutableArray *listData = [[NSMutableArray alloc] init];

for (int i = 0; i < 3; i++) { 
    MyData *obj = [[MyData alloc] init];
    NSString *name = nil;  
    switch (i)     {
        case 0:   
           name = @"Semen";   
           break;    
       case 1:         
           name = @"Ivan"; 
           break;           
       case 2:        
           name = @"Stepan";  
           break;         
       default:       
           break;  
    }         
    obj.name = name;   
    [listData addObject: obj];  
   [obj release];



[listData release];   裡面提到了3個問題,翻譯後加上我的理解:

(1)NSMutableArray這個數組裡麵包含的物件是什麼?是物件的一份拷貝,還只是一個物件的指標?

答:數組裡存放的不是物件的複本,只是物件的指標。

按以前所學的C++的思維方式,上面的這句[obj release]是最難理解的,我把obj放在數組裡,數組裡存放的是物件的引用,為什麼把obj釋放了?這樣數組裡存放了一個無效的指標?實際上還是思維方式沒有轉變過來,在Objective-C中,[obj release]只表示obj收到一個release訊息,如果它的引用計數沒有變成0,它就不會釋放,而在C++中見到這個release就想到了釋放。我們來看一個過程:

MyData *obj = [[MyData alloc] init];   //obj用了init方法,按照約定,obj的引用計數是1,並且要自已來維護釋放過程

[listData addObject: obj];    //obj在放到數組裡的時候會自動給obj的引用計數加1,這時obj的引用計數就是2

[obj release];  //為了維持obj的正常計數值,用這條語句讓obj的引用計數為1,僅此而已,並沒有被釋放掉!

[listData release]; // 這句會給obj再發一個release訊息,這樣obj的引用計數變為0,銷燬。如果前面那條語句[obj release]不寫,則obj的物件沒有正常釋放掉,就會造成記憶體洩漏!

(2)需要先釋放掉數組裡的所有物件,然後再釋放NSMutableArray物件嗎?

答:不需要。

在釋放NSMutableArray物件裡,它自動先給裡面的物件發一個release訊息。

(3)正確使用NSMutableArray的步驟是什麼? (alloc, init, work, release) 

答:

1. NSMutableArray *arr = [[NSMutableArray alloc] init];   //分配陣列

2. alloc object1.              //分配obj1

3. add object1 to array.    //把obj1加到陣列中

4. release object1.           //obj1引用計數減1

5. alloc object2.               //分配obj2

6. add object2 to array.    //把obj2加到陣列中

7. release object2.            //obj2引用計數減1

8. add as many objects as needed in this manner.  // 按上面的辦法,可以加任意多的物件

8. work with object1.        //可以訪問裡面的物件

9. remove object1 from array. it will receive a release automatically.  //也可以把obj1移除,這時obj1會自動收到一個release訊息

10. [arr release];   // object2 and others will receive a release.  最後釋放陣列,數組裡的所有元素也會自動得到一個release訊息


上述道理對於NSMutableDictionary類的setObject方法也適用。