Struggling with memory management and create array method
I'm struggling to find the correct way to release an array after my method has been called. I wonder if there is a better way to achieve what I'm trying to acheive with my method:
- (NSArray *) setupDetailArray : (NSString *) selectedCategory {
// Load .plist file
NSString *path = [[NSBundle mainBundle] pathForResource:@"data" ofType:@"plist"];
// Load .plist into a new dictionary
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
// Drill down to next level
NSArray *faceSelection = [[NSArray alloc] initWithArray:[dict objectForKey:detailTitle]];
[dict release], dict = nil;
// Set up link to App Delegate
UltimateRageAppDelegate *dataCenter = (UltimateRa开发者_如何转开发geAppDelegate *) [[UIApplication sharedApplication] delegate];
dataCenter.faces = [[NSMutableArray alloc] init];
// Set app delegate faces to array
dataCenter.faces = faceSelection;
[dataCenter.faces release];
return faceSelection;
// [faceSelection release], faceSelection = nil; ??????
}
And I call my method in viewDidLoad
// If faceArray is empty, create it
if (faceArray == nil)
faceArray = [self setupDetailArray:detailTitle];
...
My application is leaking memory here, and I'm really looking for a way to release everything once I'm done.
Your method should return an autoreleased array which is then retained by the method that calls it if it wants/needs to keep it.
- (NSArray *) setupDetailArray : (NSString *) selectedCategory {
...
// Create the array, but don't own it
NSArray *faceSelection = [[[NSArray alloc] initWithArray:[dict objectForKey:detailTitle]] autorelease];
...
return facesSelected;
}
Now the code that calls this method should retain the object if it needs it. So, in your viewDidLoad
if (faceArray == nil)
faceArray = [[self setupDetailArray:detailTitle] retain];
...
If faceArray is an instance variable in your class, then you can just release it in your dealloc method.
You are also leaking memory here
// Set up link to App Delegate
UltimateRageAppDelegate *dataCenter = (UltimateRageAppDelegate *) [[UIApplication sharedApplication] delegate];
dataCenter.faces = [[NSMutableArray alloc] init];
// Set app delegate faces to array
dataCenter.faces = faceSelection;
[dataCenter.faces release];
This should be
// Set up link to App Delegate
UltimateRageAppDelegate *dataCenter = (UltimateRageAppDelegate *) [[UIApplication sharedApplication] delegate];
dataCenter.faces = faceSelection;
I'd suggest you read (and re-read and re-read) the docs on memory management and read up on properties, setters and the dot notation.
Apple Objective-C Memory Management
dataCenter.faces = [[NSMutableArray alloc] init];
You allocate a non-autoreleased array and assign it to the property faces
(I bet it has the retain
modifier).
dataCenter.faces = faceSelection;
Now you assign as new array to the faces
property, but you haven't properly release the previous NSMutableArray.
[dataCenter.faces release];
You now indirectly release your faceSelection
array.
You leak at least one NSMutableArray every time you run that method. You should do it like this instead:
// Drill down to next level
NSArray *faceSelection = [[dict objectForKey:detailTitle] copy];
[dict release], dict = nil;
// Set up link to App Delegate
UltimateRageAppDelegate *dataCenter = (UltimateRageAppDelegate *) [[UIApplication sharedApplication] delegate];
// Set app delegate faces to array
dataCenter.faces = faceSelection;
return [faceSelection autorelease];
Your method should return an autoreleased object. The only methods that should return retained objects are methods whose name:
- starts with
alloc
- starts with
new
- contains
copy
All other methods should return autoreleased objects.
Other way for doing this.
//Declare method as follows.
- (void) setupDetailArray : (NSString *) selectedCategory arrFaceArray:(NSArray *)faceArray
{
}
And I call my method in viewDidLoad
if (!faceArray)
{
faceArray = [[NSArray alloc] init]; //Alloc in ViewDidLoad and release in ViewDidUnload or dealloc.
faceArray = [self setupDetailArray:detailTitle arrFaceArray:faceArray];
}
Also consider the @DarkDust answer for maintaining autoreleased objects. Both are the possible ways.
精彩评论