开发者

how to clear an NSMutableArray of custom objects without creating memory leaks?

If I have an NSMutableArray of custom objects, how can I must easily clear the array without causing any memory issues? Assume that the custom object class has a dealloc method in it which correctly released an instance variables etc.

For example is it ok to use the NSArray "removeAllObjects" method?

  • If yes - how does this work - does "removeAllObjects" call the "dealloc" method on each object as it removes them

  • If no - what would be the easiest approach to use?

EDIT (after 4 replies) - One last question of clarification after the great replies - I'm still not quite sure about the instance variables/properties in my custom object that I have set to retain? These seem to be 开发者_StackOverflow社区only released via the the "dealloc" method in my custom object class, where we do this manually along with [super release].

So if, re clearing an array, if I do a removeAllObjects, and then NSArray issues a "release" to my custom objects, but doesn't call "dealloc", then how do my instance variables get released?


removeAllObjects will remove the object from the array. This process will send a release message to the object and this will decrease its reference count. When the reference count reaches zero the object will be deallocated.

don't do it like this, because it will leak.

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

this is the correct way:

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

Instead of calling removeAllObjects you could just release the array. If an array is deallocated everything that's inside of it gets released and if there is no other reference to the object it will be deallocated.


Yep, just call removeAllObjects. Just to be sure, you don't call retain when you add an object to an array or when you create an array with objects. That's done for you automatically.

Regarding dealloc, again that will be done automatically, and you can't predict when.

The only thing you need to have in the dealloc is the array object itself. That is, assuming it's an instance variable or ivar?

To check everything is good, run the Analyzer using Product -> Analyze. And then give the app a profile in Instruments using the Leaks instrument to check that none of your code is causing any memory leaks.


Basically removeAllObjects method sends release message to all the objects. The release method decrements the objects reference count. And if the reference count of an object reaches 0 then the dealloc message will be sent to the object.

The answer to your question is calling [array removeAllObjects] is completely safe. By the way if you don't want the array anymore you can directly call [array release] which releases all its objects as well as the array.


The dealloc method is never called directly. Everything is done thru the retain/release mechanism (and the reference counting principle). So this is the release method that gets called, not the dealloc directly. The dealloc method is only called by the runtime if the last release call causes the reference counting (retainCount) of the object reaches zero, meaning that the object really is deallocated from memory as noone uses it anymore.

NSArray and all container classes in Cocoa (NSDictionary, NSSet, ...) do retain their values. So when you add an objet to a container like NSArray, it will retain that value. And when you remove that value (including when you call removeAllObjects") it will release it.

Memory Mgmt rules are easy to follow: but the only rule that matters it that you only have to call release or autorelease if you called alloc, retain or copy methods. That's always the responsability of the objet which did the alloc/retain/copy to call the release/autorelease. Never leave a alloc/retain/copy without a pending release/autorelease call to balance it (or you will have leaks), but on the other hand never call release/autorelease if you didn't do the alloc/retain/copy call yourself.

Good example 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.

Good example 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

Good example 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

Bad example:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜