views:

351

answers:

4

I'm trying to populate a dictionary dynamically in a for loop like so:

pseudo-code

myObject = new Object
myDict = new Dictionary
for(int i; i < 10;i++)
  myObject.value1 = new data from somewhere
  myObject.value2 = new data from somewhere
  myDic = value:myObject key:i
end for

So my question is in objective-c, can I just keep assigning new data to the myObject without releasing it every time in the loop? I'm still trying to figure out memory management in objective-c.

+5  A: 

That depends on what myObject actually is and how you have its properties defined. Assuming you have them defined to release such as here:

@property (nonatomic, retain) SomeClass *myProperty;

then yes, you can do that. The setters synthesized automatically for you by objective-c release and set to nil old values of properties before retaining and assigning new values.

However, although there is no problem with your memory management, there is still a problem with your code. Remember that myObject is a pointer, just like in C or C++. That means that if you add it to myDic and then modify the properties of the object later (such as on the next iteration of your for loop), those changes will be reflected when you pull the object out of the dictionary at some point in the future. What you want is something like this:

myObject = nil
myDict = new Dictionary
for(int i; i < 10;i++)
  myObject = new Object
  myObject.value1 = new data from somewhere
  myObject.value2 = new data from somewhere
  myDic setValue:myObject forKey:i
  myObject release
end for

What this does is release myObject after putting it in the dictionary (all cocoa collection classes retain any object you put into them and release the objects when they are either removed or the collection itself is deallocated) so you don't have a leak, as well as allocate a new instance of Object at every iteration so you aren't modifying the same object over and over again.

If you haven't been reading Apple's Memory Management Guide for Cocoa, I'd highly recommend doing so. It's very informative.

Marc W
A: 

Memory management in Objective-C is done through reference counting. When you allocate an object, it has a reference count of 1. The 'retain' method increases the reference count while 'release' decreases it. When the reference count reaches 0, the 'dealloc' method is called (you should never call 'dealloc' explicitely) and the object is freed.

You can also call 'autorelease' on an object, which will decrease the reference count "some time later". This allow you to make use of the object without worrying about releasing it.

For your question. When you add an object to a container, a 'retain' call is made on the inserted object. This means that you have to 'release' the inserted object:

NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init];
for( int i = 0; i < 10; ++i ) {
    Object *myObject = [[Object alloc] init];
    [myDict setObject:myObject forKey:[NSNumber numberWithInt:i]];
    [myObject release];
}

You could also use:

Object *myObject = [[[Object alloc] init] autorelease];

and you wouldn't have to call 'release' after the insertion.

Martin Cote
A: 

Your question is very open, it depends on how your Object and Dictionary is implemented.

First, you allocate object only once and release it in loop 10 times -> memory problem.

If we get past that. Assume that you allocate new object in every iteration of loop.

Take NSMutableDictionary and MyObject that extends NSObject as an examples of your Object and Dictionary.

When you call setObject:forKey on NSMutableDictionary instance, the object will receive retain call so dictionary keeps reference of it.

When you release it at the end of iteration the dictionary still keeps reference to it so it is ok.

Another thing to keep in mind if you use this in a big loop:

Object *myObject = [[[Object alloc] init] autorelease];

is the fact that autoreleased objects go to autorelease pool. Pool gets cleaned at the end of current event processing. If you create lots of objects it can take a lot of time to get through it at the end of event processing. In that case you might chose to create your own autorelease pool only for the loop - but I guess that's more advanced topic.

Definitely have a look at some Objective-c and memory management references from Apple.

stefanB
A: 

What you're doing works with only one object and puts that one object into the dictionary ten times. It does not put ten separate objects into the dictionary.

Peter Hosey