简体   繁体   中英

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]]; 

Any help is appreciated. Thank you.

Copy the dictionary to citiesDictionary .

NSString *plistPath = [[NSBundle mainBundle] pathForResource:map ofType:@"plist"];
NSDictionary *mapDict = [NSDictionary dictionaryWithContentsOfFile:plistPath];
citiesDictionary = [[mapDict objectForKey:@"Cities"] copy];

Now you can be sure to have copy of the dictionary even though the containing object can be released at any time. Remember then to also subsequently release the citiesDictionary.

Note when using copy that you will always get an immutable NSDictionary even if the original object was an NSMutableDictionary . Use mutableCopy to obtain an NSMutableDictionary if needed.

You're overreleasing citiesdictionary somewhere, seeing you have already called retain in the init method. Map dict will only release your citiesdictionary once when it is autoreleased, but will not cancel the retain you have done in the init method.

You should try to check your other methods for a release statement to your dictionary, or have the static analyzer tell you.

Thanks for your comments guys. After hours of banging my head against the problem I discovered what caused it.

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.

PS.: StackOverflow overlords: Given that the solution to the problem was completely unrelated to the main question, should I go and vote this question for deletion, or keep it for reference?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM