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!
dealloc
other than the memory manager (or a subclass'sdealloc
).removeAllObjects
callsrelease
on each object as it clears it from the array. – Hot Licksdealloc
in your code that is not part of[super dealloc];
you are doing it wrong. – Matthias Bauch