NSDictionary Memory leaks - iphone

I implement a method to return a dictionary in my app. But I find a memory leak using instrument, I tried to figure it out, but I still cannot find it. Can anyone help me out?
Thanks in advance, here is the code for that methods:
-(NSMutableDictionary *)initDict
{
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
[dict setObject:self.name forKey:#"Name"];
//Some similar set object for key here...
return dict;
}
I think the problem is from allocing memory for dict and not releasing it. But in the method, it seems I cannot release dict. So is there any method to fix the leak?

All variants are good. Here is third variant (choose wisely):
Replace
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
with
NSMutableDictionary *dict = [NSMutableDictionary dictionary];

I think you just need to change the last line of initDict to this:
return [dict autorelease];

When you are creating any object in your function and you want to return them then you should always create it in a way that those objects are autoreleased. So you should change your code like below.
NSMutableDictionary *dict = [[[NSMutableDictionary alloc]init]autorelease];
So whenever you create any object just call autorelease method on that.

Related

iOS NSMutabledictionary is null when I setValue and forKey

I know I may been doing something very stupid but I can not figure out where is the error on this code:
NSString *string=#"some string";
[self.dataResponse setValue:string forKey:#"Code"];
Also I tried:
NSString *string=#"some string";
[self.dataResponse setObject:string forKey:#"Code"];
but in both cases my nsmutable dictionary self.dataResponse is null. Any of you knows what I'm doing wrong?
I really appreciate your help.
You need to Alloc and Init the NSMutableArray to set values in it. Example:
self.dataResponse = [[NSMutableArray alloc] init]; // This is alloc and init
NSString *string = #"Some Val";
[self.dataResponse setValue:string forKey:#"Code"];
your variable self.dataResponse is just nil.
You have to say
self.dataResponse = [NSMutableDictionary new];
to allocate and instantiate a dictionary.
afterwards you can assign values to the keys!
I think you must not have initialised your mutable dictionary yet, wether using alloc/init or a convenience initialiser. Until you do that, setting any object for key will do nothing. You can do this lazily or in view did load (amongst other places).

Mutable deep-copy of a NSMutableDictionary

First of all I found something similar:
deep mutable copy of a NSMutableDictionary
but it didn't solve my problem.
I have a NSMutableDictionary as a template.
NSMutableDictionary *mutableDictionaryTemplate = [NSMutableDictionary dictionaryWithObjectsAndKeys: #"obj1, #"key1",#"obj2, #"key2",nil];
Now I would like to copy this dictionary, then change some parts and later save it in a NSMutable Array.
NSMutableArray *savedIterations = [NSMutableArray new];
//some loop that normally would change the objects added
int i=0;
for (i < 5){
NSMutableDictionary *copiedDictionary = [mutableDictionaryTemplate copy];
[copiedDictionary setObject:#"obj3" forKey:#"key3"];
[savedIterations addObject:copiedDictionary];
i++;
}
My problem is that once I copy the NSMutableDictionary "mutableDictionaryTemplate" it no longer is mutable. But I need to copy it because otherwise I will have the same NSMutableDictionary at every index of my NSMutableArray "savedIterations" (at least I think so). I tried mutable copy as well but there I change the "mutableDictionaryTemplate" when I change "copiedDictionary". I think I have something messed up with what I have to copy and what not and how to copy it correctly.
It would be great if someone could point me into the right direction.
You could try this:
NSMutableDictionary *destinationDictionary = (NSMutableDictionary *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (__bridge CFPropertyListRef)(sourceDictionary), kCFPropertyListMutableContainers));

NSMutableDictionary not Setting Keys

All,
I'm sure I'm overlooking something, but I've been staring at this code for too long trying to figure out what's going on.
-(IBAction)continue:(id)sender
{
//setters for the limits
NSLog(#"Log ageUnder18: %#", ageUnder18.text); //returns Y
NSMutableDictionary *cardLimits;
[cardLimits setObject:ageUnder18.text forKey:#"ageUnder18"];
NSLog(#"Just set %#", [cardLimits objectForKey:#"ageUnder18"]); //returns NULL
//more code here
}
Why is that returning NULL?
Thanks in advance,
James
You're not initializing your variable. In fact, you're rather lucky that you aren't crashing outright on the -setObject:forKey: line. Your cardLimits variable currently holds garbage memory, i.e. whatever was on the stack at the address that the variable occupies. You need to use
NSMutableDictionary *cardLimits = [NSMutableDictionary dictionary];
Note that the Static Analyzer should be able to catch this for you.
You are not allocating cardLimits at any time. You need:
NSMutableDictionary *cardLimits = [[NSMutableDictionary alloc] init];
You aren't initializing a NSMutableDictionary.

Memory management with NSDictionary

I found an answer to this a while ago, and made a mental note to fix it, but now I can't for the life of me find the post again.
Very simple - my current method for adding dictionaries to an array is leaky. Please, what is the best way to ensure they are being released properly? My method:
[beachPresenters addObject:[[NSMutableDictionary alloc]initWithObjectsAndKeys:
#"Kayak rides",#"name",#"kayak_sm.png",#"smPhoto",#"kayak_med",#"medPhoto",#"Free kayak rides for kids",#"description",#"",#"Friday",
#"All day! 10.00am - 6.00pm",#"Saturday",#"",#"Sun",#"Beach",#"stage",#"Blah blah blah",#"blurb",nil]];
beachPresenters (I assume it's an array) takes ownership of the dictionary, so the +1 to the reference count caused by +alloc/-init of the dictionary is not balanced. Thus, the dictionary is leaked.
Use the convenience method equivalent to balance the retain:
NSDictionary *presenter = [NSDictionary dictionaryWithObjectsAndKeys: ...];
[beachPresenters addObject: presenter];
Your array beachPresenters retains the mutable array you created, but your array as created in your example already has a retain count of one. So even if you dispose of beachPresenters, your dictionary will still be retained, i.e., leaked.
Use [NSMutableDictionary dictionaryWithObjectsAndKeys:] instead.
You can have implementation like below:
NSMutableDictionary *dict = [[NSMutableDictionary alloc]initWithObjectsAndKeys:
#"Kayak rides",#"name",#"kayak_sm.png",#"smPhoto",#"kayak_med",#"medPhoto",#"Free kayak rides for kids",#"description",#"",#"Friday",
#"All day! 10.00am - 6.00pm",#"Saturday",#"",#"Sun",#"Beach",#"stage",#"Blah blah blah",#"blurb",nil];
[beachPresenters addObject:dict];
[dict release];
or
NSMutableDictionary *dict = [[[NSMutableDictionary alloc]initWithObjectsAndKeys:
#"Kayak rides",#"name",#"kayak_sm.png",#"smPhoto",#"kayak_med",#"medPhoto",#"Free kayak rides for kids",#"description",#"",#"Friday",
#"All day! 10.00am - 6.00pm",#"Saturday",#"",#"Sun",#"Beach",#"stage",#"Blah blah blah",#"blurb",nil] autorelease];

iphone how to release memory in this case

I have a method like this
- (NSDictionary *)getCellValuesForRow:(int)row {
NSMutableDictionary *dictValues= [[NSMutableDictionary alloc] init];
Outage *outage = [listOutage objectAtIndex:row];
[dictValues setObject:outage.duration forKey:#"OutageDuration"];
return dictValues;
}
and this value is stored in this way
NSDictionary *dict = [[NSDictionary alloc] initWithDictionary:[self getCellValuesForRow:(indexPath.row-1)]];
how to release memory in this scenario
This is what autorelease is for.
NSMutableDictionary *dictValues= [[[NSMutableDictionary alloc] init] autorelease];
You should autorelease dictValues in getCellValuesForRow, or just don't alloc it. This will keep it autoreleased:
NSMutableDictionary *dictValues= [NSMutableDictionary dictionary];
In most cases it should be the responsibility of whatever calls it to alloc it (if it needs to be kept around after the autorelease pool is cleared), then dealloc it later.
If whatever calls it doesn't need it kept around, it can just leave it autoreleased.
An alternative is to simply use
NSMutableDictionary *dictValues= [NSMutableDictionary dictionary];
That's effectively the same thing as what Dan suggested. Just less typing.
It applies to your next line, too:
NSDictionary *dict = [NSDictionary dictionaryWithDictionary:[self getCellValuesForRow:(indexPath.row-1)];