views:

1494

answers:

6

This is not a garbage collected environment

I have a class instance variable which at some point in my runtime, I need to re-initialize with a different data set than it was originally constructed with.

Hypothetically speaking, what if I have an NSMutableArray or an NSMutableDictionary, would it be more efficient to do something such as:

[myArr release];
myArr  = [[NSMutableArray alloc] init....];

or just,

myArr = nil;

Will myArr release the object and leave me without a pointer to the storage in memory so I can re-use myArr?

+14  A: 

If you do myArr=nil; by itself, then you've lost the pointer to which you can send the release message to. There is no magic to release your object.

And, as gs says, without being able to release your object, that memory has 'leaked'.

Abizern
And there's the memory leak.
Georg
+1  A: 

One way to realize the difference might be this: Setting a reference to an object to nil does nothing to the object, it only does something to the reference.

"Releasing the object" is not "nothing", so it doesn't do that. :) In a garbage-collected language it might do that as a side-effect of dropping the reference, but in Objective C it doesn't work that way.

unwind
+4  A: 

If you were on Mac OS, not iPhone OS I would say that it depends on whether the garbage collector is activated or not:

  • with GC: use myArr = nil;
  • without GC: use [myArr release];

Unfortunately, on iPhone, there is no garbage collection, so if you don't want memory leaks, you have to release your object once you no longer need it.

mouviciel
No GC on iPhone.
Abizern
Yes you are right. I am too focused on Mac OS... My answer is updated.
mouviciel
You don't even need to set it to nil, as this happens mostly in the dealloc code when the upper object with all it's links is collected.
Georg
+5  A: 

You could use a property and get almost the syntax you want without the memory leak.

Use this syntax to declare the array

@property (readwrite, retain) NSMutableArray *myArray;

Then re-initialize it like this:

[self setMyArray:[NSMutableArray array]];
Lounges
Or to use the dot-property syntax: self.myArray = [NSMutableArray array];
Daniel Dickison
as myArray points to a mutable object, better form would be @property(readwrite, copy)NSMutableArray *myArray
Abizern
+1  A: 

If what you want is to reset the contents of an NSMutableArray/NSMutableDictionary, you can also call removeAllObjects and you have a fresh array/dict to work with.

+2  A: 

The first code block is fine. However, the second block does not leave you with an array you can use so it is not sufficient. Half correcting that block, I think you mean:

myArr = nil;
myArr = [[NSMutableArray alloc] init....];

However, this does not accomplish what you want either because you are not releasing myArr. If you have synthesized a setter for myArr, then you can get the release behavior you want from setting to nil, by using the setter (self.myArr) instead of accessing the pointer directly (myArr). Correcting your second block fully:

self.myArr = nil;
myArr = [[NSMutableArray alloc] init....];

Now we have equivalent code examples, one using setter with nil to release, the other not. They are the same.

If myArr is a mutable array as in these examples, the most efficient method is to use removeAllObjects, avoiding all the work of releasing memory only to claim it back:

[myArr removeAllObjects];
Roger
Re #2: Furthermore, you can use the setter with the new array as well (passing an autoreleased array, `[NSMutableArray array]`), and then use array accessors to fill it out. http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ModelObjects/Articles/moAccessorMethods.html Of course, if you're going to populate the new array immediately, it'd be more efficient to do that with the new array in a local variable, then set the property to the finished array. And either of these methods would not require setting the property to `nil` first.
Peter Hosey