2011-09-29 48 views
14

如果我有一個自定義對象的NSMutableArray,我怎樣才能輕鬆清除數組而不會造成任何內存問題?假設自定義對象類有一個dealloc方法,它可以正確釋放實例變量等。如何清除自定義對象的NSMutableArray而不會造成內存泄漏?

例如,可以使用NSArray「removeAllObjects」方法嗎?

  • 如果是 - 如何工作 - 不「removeAllObjects」調用每個對象的「的dealloc」的方法,因爲它消除他們

  • 如果沒有 - 這將是最簡單的方法使用?

EDIT(後4篇回覆) - 最後一個明確的答覆大問題後 - 我仍然不十分肯定,我已經設置保留實例變量/在我的自定義對象的屬性?這些似乎只能通過我的自定義對象類中的「dealloc」方法發佈,我們在這裏手動執行此操作以及[超級發佈]。所以如果重新清理一個數組,如果我做了一個removeAllObjects,然後NSArray向我的自定義對象發出「釋放」,但不調用「dealloc」,那麼我的實例變量是如何釋放的呢?

+1

任何人都不應該叫'比內存管理器(或子類的'dealloc')dealloc'等。當removeAllObjects從數組中清除它時,removeAllObjects在每個對象上調用'release'。 –

+2

是的,如果你在代碼中看到'dealloc'不是'[super dealloc]的一部分;'你做錯了。 –

回答

31

​​將從數組中移除該對象。此過程將向對象發送釋放消息,這將減少其引用計數。當引用計數達到零時,對象將被釋放。

不這樣做,因爲它會泄漏。

NSObject *object = [[NSObject alloc] init];  + 1 
[array addObject:object];       + 1 
[array removeAllObjects];       - 1 
               ======= 
               = + 1 -> Leak 

這是正確的方式:

NSObject *object = [[[NSObject alloc] init] autorelease]; + 1 (from alloc) - 1 (from autorelease) 
[array addObject:object];       + 1 
[array removeAllObjects];       - 1 
               ======= 
               = 0 -> Object will be deallocated 

而不是調用removeAllObjects的你可能只是釋放陣列。如果一個數組被釋放,那麼它內部的所有內容都會被釋放,如果沒有其他對該對象的引用,它將被釋放。

+0

謝謝 - 只是在我的問題中添加了一個澄清問題作爲編輯在我的問題中,如果沒關係...... – Greg

+0

對於我遲來的答案感到遺憾,但一旦引用計數達到零,系統就會調用對象上的dealloc。你不必這樣做。 –

+5

使用ARC時,系統以第一種方式正確處理這種情況,不是嗎? – Alex

3

是的,只需撥打​​。可以肯定的是,當您將一個對象添加到一個數組或者當您使用對象創建一個數組時,您不會調用retain。這是爲你自動完成的。

關於dealloc,這又會自動完成,並且您無法預測何時。

你需要在dealloc中唯一需要的是數組對象本身。也就是說,假設它是一個實例變量或ivar?

要檢查一切正常,請使用產品 - >分析運行分析儀。然後使用Leaks工具在儀器中給應用程序一個配置文件來檢查您的代碼是否沒有導致任何內存泄漏。

1

dealloc方法從不直接調用。一切都通過retain/release機制(和引用計數原理)完成。所以這是被調用的release方法,而不是直接的dealloc。該dealloc方法由運行時,如果最後release調用導致對象的引用計數(retainCount)達到零,這意味着真正的對象從內存中沒有人使用它了釋放只叫。

NSArray和Cocoa中的所有容器類(NSDictionary,NSSet,...)都保留它們的值。因此,當您向像NSArray這樣的容器添加對象時,該值將爲retain。而當你刪除值(包括當你調用removeAllObjects「),它會release

內存管理的規則很容易遵循。但重要的是唯一的規則,你只需要調用releaseautorelease如果你叫allocretaincopy方法。這一直是該做的alloc/retain/copy調用release/autorelease的客體的責任。切勿用alloc/retain/copy沒有未決release/autorelease調用來平衡它(或者你將有泄漏),但另一方面從來沒有調用release/autorelease,如果你沒有做alloc/retain/copy自稱。

好實施例1:

MyClass* obj = [[MyClass alloc] init]; // here you do an alloc 
[myArray addObject:obj]; // the NSArray "myArray" retains the object obj 
// so now you can release it, the array has the responsability of the object while it is held in the array 
[obj release]; // this release balance the "alloc" on the first line, so that's good 

[myArray removeAllObjects]; // there the object held by the array receive a release while being removed from the array. As nobody retains it anymore, its dealloc method will be called automatically. 

良好實施例2:

MyClass* obj = [[MyClass alloc] init]; // here you do an alloc 
[myArray addObject:obj]; // the NSArray "myArray" retains the object obj 
// so now you can release it, the array has the responsability of the object while it is held in the array 
[myArray removeAllObjects]; // there the object held by the array receive a release while being removed from the array. But your own code still retains a reference to it (because of the "alloc" on first line) so it won't be removed from memory right now 
[obj release]; // this release balance the "alloc" on the first line, and as nobody retains the object anymore, its dealloc method will be called and it will be deallocated from memory 

良好實施例3:

MyClass* obj = [self getSomeObjectFromAnotherMethod]; // here you don't have an "alloc" on this line 
[myArray addObject:obj]; // the array retains the object 
[myArray removeAllObjects]; // the array release the object while it removes it from the array 
// no need to call "release" here as there is no "alloc" done in the scope of this code 

爲例如:

MyClass* obj = [self getSomeObjectFromAnotherMethod]; // here you don't have an "alloc" on this line 
[myArray addObject:obj]; // the array retains the object 
[myArray removeAllObjects]; // the array release the object while it removes it from the array 
[obj release]; // Crash here! obj does not exists anymore and has been deallocated from memory before this line! 
+0

謝謝 - 只是在我的問題中添加了一個澄清問題作爲編輯,如果沒關係的話...... – Greg

1

基本上​​方法向所有對象發送release消息。所述釋放方法遞減對象引用計數。如果對象的引用計數達到0,則將發送dealloc消息給對象。

的回答你的問題是調用[array removeAllObjects]是完全安全的。順便說一句,如果你不想再使用這個數組,你可以直接調用[array release]來釋放它的所有對象以及數組。

+0

你說它發送一個釋放方法ipso facto。那是因爲ARC嗎? –