Here are two methods that return a dictionary of my custom four-propery objects. They make arrays of strings, floats and BOOLs to put in the Chemical objects, then build a dictionary from the arrays. I’m new enough to the whole memory management game that I’m not always sure when I own something and when to release it. I’m making all kinds of strings on the fly.
Here’s the thing: The static analyzer sees no problem with the first method, - (id)generateChlorineDictionary but says there’s a leak in the second one, - (id)generateCYADictionary. It says it starts at the NSMutableArray *cyaGranulesArray... and then goes to NSDictionary *cyaDictionary... and finally to the return cyaDictionary statement.
Here are the two methods; sorry they’re so long!
EDIT: Changed name from generateChlorineDictionary to newChlorineDictionary
Removed a release that happened after the return
- (id)newChlorineDictionary {
// Sets up the array for the Bleach key
NSMutableArray *bleachArray = [[NSMutableArray alloc] init];
NSArray *bleachConcentrationArray = [[NSArray alloc] initWithObjects:@"6%", @"10%", @"12%", nil];
float bleachConstantArray[] = {0.0021400, 0.0012840, 0.0010700};
for (int i=0; i<3; i++) {
Chemical *bleachChemical = [[Chemical alloc] initWithChemical:@"Bleach"
andConcentration:[bleachConcentrationArray objectAtIndex:i]
andConstant:bleachConstantArray[i]
andIsLiquid:YES];
[bleachArray addObject:bleachChemical];
NSLog(@"bleachChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", bleachChemical.chemName, bleachChemical.chemConcentration, bleachChemical.chemConstant, bleachChemical.chemIsLiquid);
[bleachChemical release];
}
bleachConcentrationArray = nil;
// Sets up the array for the Trichlor key
NSMutableArray *trichlorArray = [[NSMutableArray alloc] init];
Chemical *trichlorChemical = [[Chemical alloc] initWithChemical:@"Trichlor"
andConcentration:@"90%"
andConstant:0.0001480
andIsLiquid:NO];
[trichlorArray addObject:trichlorChemical];
NSLog(@"trichlorChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", trichlorChemical.chemName, trichlorChemical.chemConcentration, trichlorChemical.chemConstant, trichlorChemical.chemIsLiquid);
[trichlorChemical release];
// Sets up the array for the Dichlor key
NSMutableArray *dichlorArray = [[NSMutableArray alloc] init];
NSArray *dichlorConcentrationArray = [[NSArray alloc] initWithObjects:@"56%", @"62%", nil];
float dichlorConstantArray[] = {0.0002400, 0.0002168};
for (int i=0; i<2; i++) {
Chemical *dichlorChemical = [[Chemical alloc] initWithChemical:@"Dichlor"
andConcentration:[dichlorConcentrationArray objectAtIndex:i]
andConstant:dichlorConstantArray[i]
andIsLiquid:NO];
[dichlorArray addObject:dichlorChemical];
NSLog(@"dichlorChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", dichlorChemical.chemName, dichlorChemical.chemConcentration, dichlorChemical.chemConstant, dichlorChemical.chemIsLiquid);
[dichlorChemical release];
}
dichlorConcentrationArray = nil;
// Sets up the array for the Cal Hypo key
NSMutableArray *calHypoArray = [[NSMutableArray alloc] init];
NSArray *calHypoConcentrationArray = [[NSArray alloc] initWithObjects:@"48%", @"53%", @"65", @"73", nil];
float calHypoConstantArray[] = {0.0002817, 0.0002551, 0.0002080, 0.0001852};
for (int i=0; i<2; i++) {
Chemical *calHypoChemical = [[Chemical alloc] initWithChemical:@"Cal Hypo"
andConcentration:[calHypoConcentrationArray objectAtIndex:i]
andConstant:calHypoConstantArray[i]
andIsLiquid:NO];
[calHypoArray addObject:calHypoChemical];
NSLog(@"calHypoChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", calHypoChemical.chemName, calHypoChemical.chemConcentration, calHypoChemical.chemConstant, calHypoChemical.chemIsLiquid);
[calHypoChemical release];
}
calHypoConcentrationArray = nil;
// Sets up the array for the Li Hypo key
NSMutableArray *liHypoArray = [[NSMutableArray alloc] init];
Chemical *liHypoChemical = [[Chemical alloc] initWithChemical:@"Li Hypo"
andConcentration:@"90%"
andConstant:0.0003800
andIsLiquid:NO];
[liHypoArray addObject:liHypoChemical];
NSLog(@"liHypoChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", liHypoChemical.chemName, liHypoChemical.chemConcentration, liHypoChemical.chemConstant, liHypoChemical.chemIsLiquid);
[liHypoChemical release];
// The array of keys for the chlorine chemicals
NSArray *chlorineKeys = [[NSArray alloc] initWithObjects:@"Bleach", @"Trichlor", @"Dichlor", @"Cal Hypo", @"Li Hypo", nil];
// The array of values for the chlorine chemicals
NSArray *chlorineValues = [[NSArray alloc] initWithObjects:bleachArray, trichlorArray, dichlorArray, calHypoArray, liHypoArray, nil];
[bleachArray release];
[trichlorArray release];
[dichlorArray release];
[calHypoArray release];
[liHypoArray release];
// The dictionary to hold the arrays of chlorine chemical objects
NSDictionary *chlorineDictionary = [[NSDictionary alloc] initWithObjects:chlorineValues forKeys:chlorineKeys];
[chlorineValues release];
[chlorineKeys release];
return chlorineDictionary;
}
EDIT: Changed name from generateCYADictionary to newCYADictionary
Removed a release that happened after the return
- (id)newCYADictionary {
// Sets up the array for the CYA Granules key
NSMutableArray *cyaGranulesArray = [[NSMutableArray alloc] init];
Chemical *cyaGranulesChemical = [[Chemical alloc] initWithChemical:@"CYA Granules"
andConcentration:@""
andConstant:0.0001330
andIsLiquid:NO];
[cyaGranulesArray addObject:cyaGranulesChemical];
NSLog(@"cyaGranulesChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", cyaGranulesChemical.chemName, cyaGranulesChemical.chemConcentration, cyaGranulesChemical.chemConstant, cyaGranulesChemical.chemIsLiquid);
[cyaGranulesChemical release];
// Sets up the array for the Liquid Stabilizer key
NSMutableArray *liquidStabilizerArray = [[NSMutableArray alloc] init];
Chemical *liquidStabilizerChemical = [[Chemical alloc] initWithChemical:@"Liquid Stabilizer"
andConcentration:@""
andConstant:0.0003460
andIsLiquid:YES];
[liquidStabilizerArray addObject:liquidStabilizerChemical];
NSLog(@"liquidStabilizerChemical: chemName = %@, chemConcentration = %@, chemConstant = %1.6f, chemIsLiquid = %d", liquidStabilizerChemical.chemName, liquidStabilizerChemical.chemConcentration, liquidStabilizerChemical.chemConstant, liquidStabilizerChemical.chemIsLiquid);
[liquidStabilizerChemical release];
// The array of keys for the CYA chemicals
NSArray *cyaKeys = [[NSArray alloc] initWithObjects:@"CYA Granules", @"Liquid Stabilizer", nil];
// The array of values for the CYA chemicals
NSArray *cyaValues = [[NSArray alloc] initWithObjects:cyaGranulesArray, liquidStabilizerArray, nil];
[cyaGranulesArray release];
[liquidStabilizerArray release];
// The dictionary to hold the arrays of CYA chemical objects
NSDictionary *cyaDictionary = [[NSDictionary alloc] initWithObjects:cyaValues forKeys:cyaKeys];
[cyaKeys release];
[cyaValues release];
return cyaDictionary;
}
Replace the
With
Or, you might replace the
With
Instead of adding the
autorelease.In your original implementation the
[cyaDictionary release];is never executed (because it is afterreturn).You can use this dictionary outside this method and you shouldn’t release it there.
You might want also return a retained object (without the
autorelease) and release it outside the method. In this case you should start the method name with “new” or “alloc”…EDIT (Important):
You should use only one of my suggestions.
autoreleasein thereturnlinedictionaryWith...If you replace the
alloc initwithdictionaryWith...then you get an autoreleased object. And then, if you release it in the outer method then you have a serious problem (the object will try to release itself after the current runloop of the thread and it may crash the app because the object will already be released by you).EDIT (due to one of the comments)
If you want to create a property that will return a dictionary: