Борьба с управлением памятью и создание метода массива - PullRequest
1 голос
/ 04 июля 2011

Я пытаюсь найти правильный способ освобождения массива после вызова моего метода.Интересно, есть ли лучший способ добиться того, что я пытаюсь достичь с помощью моего метода:

- (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 = (UltimateRageAppDelegate *) [[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; ?????? 

}

И я вызываю мой метод в viewDidLoad

// If faceArray is empty, create it
if (faceArray == nil)
    faceArray = [self setupDetailArray:detailTitle];
...

У меня утечка приложенияпамять здесь, и я действительно ищу способ освободить все, как только я закончу.

Ответы [ 3 ]

2 голосов
/ 04 июля 2011

Ваш метод должен возвращать автоматически освобожденный массив, который затем сохраняется методом, который вызывает его, если он хочет / должен его сохранить.

- (NSArray *) setupDetailArray : (NSString *) selectedCategory {
...
// Create the array, but don't own it
NSArray *faceSelection = [[[NSArray alloc] initWithArray:[dict objectForKey:detailTitle]] autorelease];
...
return facesSelected;
}

Теперь код, который вызывает этот метод, должен сохранять объект, если он ему нужен. Итак, по вашему мнению DidLoad

if (faceArray == nil)
    faceArray = [[self setupDetailArray:detailTitle] retain];
...

Если faceArray - переменная экземпляра в вашем классе, вы можете просто освободить ее в своем методе dealloc.

У вас также есть утечка памяти здесь

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

Это должно быть

// Set up link to App Delegate
    UltimateRageAppDelegate *dataCenter = (UltimateRageAppDelegate *) [[UIApplication sharedApplication] delegate];
    dataCenter.faces = faceSelection;

Я бы посоветовал вам прочитать (и перечитать и перечитать) документы по управлению памятью и прочитать о свойствах, установщиках и точечной записи.

Управление памятью Apple Objective-C

1 голос
/ 04 июля 2011

Другой способ сделать это.

//Declare method as follows. 
- (void) setupDetailArray : (NSString *) selectedCategory arrFaceArray:(NSArray *)faceArray
{
}

И я вызываю мой метод в viewDidLoad

if (!faceArray)
{
    faceArray = [[NSArray alloc] init]; //Alloc in ViewDidLoad and release in ViewDidUnload or dealloc.
    faceArray = [self setupDetailArray:detailTitle arrFaceArray:faceArray]; 
}

Также рассмотрим ответ @DarkDust для поддержки автоматически выпущенных объектов.Оба возможных пути.

1 голос
/ 04 июля 2011
dataCenter.faces = [[NSMutableArray alloc] init];

Вы выделяете массив без автоматического освобождения и присваиваете его свойству faces (держу пари, у него модификатор retain).

dataCenter.faces = faceSelection;

Теперь вы присваиваете новый массив свойству faces, но не выполнили должным образом предыдущий NSMutableArray.

[dataCenter.faces release];

Теперь вы косвенно освобождаете массив faceSelection.

Вы пропускаете хотя бы один NSMutableArray при каждом запуске этого метода. Вы должны сделать это следующим образом:

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

Ваш метод должен возвращать автоматически освобожденный объект. Единственными методами, которые должны возвращать сохраненные объекты, являются методы, имя которых:

  • начинается с alloc
  • начинается с new
  • содержит copy

Все остальные методы должны возвращать автоматически освобожденные объекты.

...