views:

516

answers:

2

When I get a memory warning I am releasing a bunch of objects stored in an NSMutableArray.

[_children release];

I also need to recurse through objects at some point (potentially after a mem warning has happened), so I need to check if the objects are still around, which I do with comparison to nil- which isn't going to work because releasing the array doesn't nil anything.

I can't loop through the array removing objects 1-by-1 and setting to nil because I'm not allowed to modify an array during iteration.

It feels like I'm missing something obvious. I just want to release + nil some values in an array.

A: 

Assuming that you aren't retaining the array elements elsewhere, surely by removing an object from the array, or releasing the array itself you are also releasing the element(s). I think that is as much as you need to do.

From the Apple documentation:

each object receives a retain message before its id is added to the array and a release message when it is removed from the array or when the array is deallocated

teabot
But how do I know that it has been released? I can't query it since it doesn't exist, and it leaves me with a dangling pointer...
Sam
Because the Apple API says so. It says that if your remove an object from an array, or release the array - the array object WILL be released.
teabot
You misunderstand- I can't do if (appleAPISaysThisObjectIsReleasedOrNot()) at runtime. I found a workaround, so thanks anyway.
Sam
+4  A: 

Sorry, but what you are doing seems pointless to me. You cannot set an object to nil, you can only set the reference to an object to nil, but that has on influence on other references.

NSObject * a = [[NSObject alloc] init];
NSObject * b = a;

[a release];
a = nil;

// b is NOT nil! b still points to the memory location where
// a used to be, which is now not valid anymore and using b
// for anything may crash your application!

If I put "a" into an array and then remove it again from the array, the retain count of "a" is decreased by one. Either it is then still bigger than zero, in which case "a" will not be released or it is zero, in which case it is released. Setting the reference to a to nil after it was released has no influence on other variables still pointing to "a".

So even if NSArray was setting the reference to "a" to nil after removing it to the array and releasing it (because its ref count got zero), it will have no affect on an instance variable still pointing to "a".

I'm not really sure what you are trying to do and it is certainly possible, but you are on a totally wrong track here.

Mecki
Thanks for the clarification. I *was* on the wrong track and found a workaround. I'm from a C++ background so this wasn't immediately obvious. In your example I would have assumed b == nil
Sam
As I don't know what you are really doing, I could not suggest a better solution. If the objects in the array are your own classes, you can of course override dealloc method (which is called when retained count reaches zero) and there notify other objects (e.g. delegates or just broadcast a notification) that you are now going die so all other objects can update their references to you to nil.
Mecki
Even in C++, if you have a pointer to an object the address you are holding would not be cleared when the object itself was destroyed - you'd have an invalid pointer, just like Objective-C when the retain count falls to 0 and you still have a reference pointing to where the memory used to be allocated...
Kendall Helmstetter Gelner