开发者

Struggling with memory management and create array method

开发者 https://www.devze.com 2023-03-17 07:24 出处:网络
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:

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消