Search code examples
objective-ciosmemory-managementnsdictionary

Objective-C: Retaining a NSDictionary inside an autoreleased NSDictionary


I have a big NSDictionary with a smaller NSDictionary inside. I want to autorelease the bigger one, and retain the second. I have this code in my init method:

// Autoreleased stage dictionary
NSString *plistPath = [[NSBundle mainBundle] pathForResource:map ofType:@"plist"];
NSDictionary *mapDict = [NSDictionary dictionaryWithContentsOfFile:plistPath];

// Owned items
citiesDictionary = [[mapDict objectForKey:@"Cities"] retain];

citiesDictionary is declared in the class interface as an:

NSDictionary *citiesDictionary;

If I try to release citiesDictionary in dealloc using the following line it crashes.

[citiesDictionary release];

But if I don't dealloc citiesDictionary, I get a memory leak reported in Instruments when I dealloc the class containing citiesDictionary. I acknowledge that mapDict is being deallocated at the end of init. Does this deallocation affects citiesDictionary even though I called retain on it?

If so, how can I keep the smaller dictionary while freeing the bigger containing one? I tried different things when assigning citiesDictionary, but nothing seems to work correctly. Some of the approaches I tried:

citiesDictionary = [[mapDict objectForKey:@"Cities"] copy];

and

citiesDictionary = [NSDictionary initWithDictionary:[mapDict objectForKey:@"Cities"]];

and even

 citiesDictionary = [NSDictionary initWithDictionary:[[mapDict objectForKey:@"Cities"] copy]];

Solution

  • It was completely my fault: I was inserting a memory-management flawed custom class inside a NSMutableDictionary related to the citiesDictionary, and freeing that other thing was causing the memory to go corrupt.

    Now, both

    citiesDictionary = [[mapDict objectForKey:@"Cities"] release];
    

    and

    citiesDictionary = [[mapDict objectForKey:@"Cities"] copy];
    

    work perfectly fine.