Objective-C / iPhone управление памятью - PullRequest
2 голосов
/ 22 августа 2009

В моем приложении для iPhone у меня есть представление «статистика», которое отображается следующим методом - сам метод вызывается, когда пользователь касается кнопки. Этот метод в UINavigationController

- (void) showStatsView {
    StatsViewController *statsViewController = [[StatsViewController alloc] initWithNibName:@"Stats" bundle:[NSBundle mainBundle]];
    [self pushViewController:statsViewController animated:YES];
    [statsViewController release]; //                       (1)
}

В самом статистическом представлении используется NSDictionary, "statsDict". Он объявлен как свойство со следующими параметрами: (nonatomic, retain).

В моем StatsViewController метод viewDidLoad создает экземпляр NSDictionary следующим образом:

MyAppDelegate *appDelegate= (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
stats = [[NSDictionary alloc] initWithContentsOfFile:[appDelegate statsFilePath]];

Мой метод dealloc для StatsViewController выглядит следующим образом:

 - (void)dealloc {

    /* 
    dealloc'ing other stuff here which is irrelavent
    */
    [statsDict release]; //                 (2)
    [super dealloc];
}

Моя проблема возникает, если я пытаюсь перезагрузить представление статистики после того, как оно было показано один раз, то есть - я нажимаю кнопку, вызывающую срабатывание showStatsView, которая загружает представление статистики (впервые), и все в настоящее время исправно ,

Если я затем нажму кнопку в представлении статистики, чтобы вернуться обратно в главное меню (что осуществляется с помощью вызова метода, использующего [self popToViewController:MainMenuViewController];) - отсюда, если я нажму кнопку, которая загружает представление статистики снова (во второй раз) мое приложение вылетает с EXC_BAD_ACCESS.

Если я удалю строку, помеченную (1) в showStatsView, то она будет работать нормально, как если бы я удалила строку, помеченную (2), в dealloc. Однако из того, что я прочитал, я должен выпустить statsDict, как я его выделил, аналогично, я должен выпустить statsViewController, как я это и выделил. Однако, если я сделаю и то и другое - это вылетит! Что мне делать?

Пропустил ли я какой-то шаг в моем понимании управления памятью target-c?

Ответы [ 2 ]

2 голосов
/ 22 августа 2009

Ваше понимание контракта кажется правильным (при условии, что вы имеете в виду "statsDict =", где вы говорите "stats =").

Так что проблема в другом, вероятно, в другом месте нарушается договор.

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

1 голос
/ 22 августа 2009

Причина, по которой ваше приложение не падает, когда вы удаляете (1) или (2), заключается в том, что оба из них имеют эффект преднамеренной утечки словаря (в точке 2 при утечке словаря и в точке 1 при утечке владелец словаря, так что -dealloc никогда не вызывают.) Очевидно, это не то, что вы хотите сделать. Вы правильно понимаете контракт, но я думаю, что вы неправильно понимаете, как инициализируется ваш объект.

Вы не воспроизводили здесь свой -init-код, но, думаю, проблема здесь в том, что -viewDidLoad вызывается только один раз, когда представление неархивировано. Поэтому при последующих созданиях statsViewController словарь не выделяется.

Если вы переместите строку, выделяющую и вставляющую NSDictionary из -viewDidLoad в метод -init statsViewController, все будет хорошо работать без необходимости преднамеренной утечки объектов. -init будет вызываться каждый раз, когда вы создаете новый statsViewController. Если у вас нет метода -init, создайте его (и не забудьте вызвать [super init]).

Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...