views:

349

answers:

4

I have a pretty simple question. While I am fairly new to Objective-C, I have gotten pretty comfortable with the language and the memory management model.

I understand ownership pretty well and the notion of explicit and implicit. I also understand that when you add anything to a collection, it takes ownership of the keys and values and releases that ownership on release.

My question relates to the releasing of a collection of collections (aka a Bag). I have the following code:


    // levelDict is a member NSMutableDictionary on the Class

    BOOL newDict = NO;
    BOOL newArray = NO;

    NSNumber *levelKey = [NSNumber numberWithInt:toLevel];
    NSMutableDictionary *dict = [levelDict objectForKey:levelKey];
    if ( dict == nil ) {
     dict = [[NSMutableDictionary alloc] init];
     [levelDict setObject:dict forKey:levelKey];
     newDict = YES;
    }

    // Now look for the array...
    NSNumber *typeKey = [NSNumber numberWithInt:objectType];
    NSMutableArray *array = [dict objectForKey:typeKey];
    if ( array == nil ) {
     array = [[NSMutableArray alloc] init];
     [dict setObject:array forKey:typeKey];
     newArray = YES;
    }

    // Now add the object to the array...
    [array addObject:object];

    // Deal with our memory management
    if ( newArray ) {
     [array release];
    }

    if ( newDict ) {
     [dict release];
    }

This code creates a Map where each entry then contains an Array (aka Bag). If I release the dictionary object levelDict which owns the array of objects for each entry, I am assuming that release will cascade through the arrays as well? Or do I have to iterate over the dictionary and explicitly release each of the arrays?

Now for the extra credit question - why am I doing this versus defining a single object of collections? Well, in other languages like Java, Object instantiation can get very expensive. I am assuming this is the case with Objective-C. Maps of associative arrays are very efficient.

Thanks Bryan

+3  A: 

When a dictionary is released, all keys and values are released. If they are arrays, releasing them will also release all entries in the array, and so on.

Of course, adding anything to a dictionary will retain the keys and values, and adding anything to a mutable array will retain the entries.

Pretty straightforward...

Philippe Leybaert
Thanks! I was pretty sure that was the case but wanted confirmation.
A: 

As long as the NSDictionary is the only container retaining a reference to a given NSObject (NSArray included), it will get deallocated when the NSDictionary does.

fbrereto
+1  A: 

From the Collections programming guide: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Collections/Articles/Arrays.html

"And when you add an object to an Objective-C array, the object isn’t copied, but rather receives a retain message before its id is added to the array. When an array is deallocated, each element is sent a release message."

Dictionaries and Sets behave the same way.

Dave DeLong
A: 

Code is simpler using autoreleased dict/array since the branching doesn't affect the retain count.

// levelDict is a member NSMutableDictionary on the Class

NSNumber *levelKey = [NSNumber numberWithInt:toLevel];
NSMutableDictionary *dict = [levelDict objectForKey:levelKey];
if ( dict == nil ) {
    dict = [NSMutableDictionary dictionary];
    [levelDict setObject:dict forKey:levelKey];
}

// Now look for the array...
NSNumber *typeKey = [NSNumber numberWithInt:objectType];
NSMutableArray *array = [dict objectForKey:typeKey];
if ( array == nil ) {
    array = [NSMutableArray array];
    [dict setObject:array forKey:typeKey];
}

// Now add the object to the array...
[array addObject:object];
Jason Harwig