Память иерархической таблицы никогда не освобождается - PullRequest
2 голосов
/ 15 апреля 2009

в очень хорошей книге «Начало разработки iPhone» (Apress) в главе 9 они объясняют, как создать приложение с контроллером навигации и иерархическими представлениями таблиц.
Если вы запускаете приложение с монитором Instrument / Activity, приложение работает хорошо, но с большой проблемой: каждый раз, когда вы переходите от табличных представлений к дочерним таблицам, это занимает 1Мо памяти больше! и эта память никогда не освобождается и, конечно же, в конце происходит сбой приложения. Для меня проблема возникла из следующего метода "RootViewController.h":
(исходный код «09 Nav» этого ZIP-файла )

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger row = [indexPath row];
    SecondLevelViewController *nextController = [self.controllers objectAtIndex:row];

    NavAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    [delegate.navController pushViewController:nextController animated:YES];

}

в этом методе «nextcontroller» никогда не выпускается. чтобы использовать команду [nextController release]; Я сделал следующую модификацию:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSUInteger row = [indexPath row];
    SecondLevelViewController *nextController = [[SecondLevelViewController alloc] init ];
    nextController = [self.controllers objectAtIndex:row];
    NavAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
    [delegate.navController pushViewController:nextController animated:YES];
    [nextController release];
}

Теперь, если вы запустите приложение, память будет освобождена! Но если вы попытаетесь развернуть дочернюю таблицу, где вы уже «побывали», произойдет сбой приложения.

Как правильно освободить память?
Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 16 апреля 2009

Я не знал инструментов "Clang Checker". Спасибо, что потратили время на его тестирование. «Clang Checker» кажется очень мощным, я попробую.

Я полностью согласен с вами RootViewController: «nextController» не утечка, а очиститель памяти. Если вы запускаете приложение с помощью Instrument / Activity monitor, в начале приложение занимает 7 месяцев, а каждый раз, когда вы переходите в дочернюю таблицу, требуется еще 1 месяц памяти:

  • через 10 раз приложение занимает 17Mo,
  • через 20 раз приложение занимает 27 мес.

и так в конце происходит сбой приложения (если я хорошо помню, приложение не может занять более 40Mo), и это приложение не следует правилам Apple в плане управления памятью.

С моей модификацией, когда вы входите в дочернюю таблицу, она занимает 1Mo памяти, но когда вы возвращаетесь к «корневой» таблице, 1Mo памяти освобождается. Вы можете перейти в другой дочерний стол, возвращаясь, память освобождается. «Единственная» проблема заключается в том, что если вы снова зайдете в дочернюю таблицу, которую уже посетили, произойдет сбой приложения. Итак, я ищу решение, которое заставит приложение освободить память после посещения дочерней таблицы.

Чтобы проверить с помощью монитора инструментов / активности, я следил за памятью, используемой приложением Apple Settings (также приложением с иерархическим представлением таблицы). Когда вы переходите в дочернюю таблицу, требуется 1 месяц память, но когда вы вернетесь, память освобождается.

1 голос
/ 16 апреля 2009

если вы проверите исходный код с помощью средства проверки Clang (http://clang.llvm.org/StaticAnalysis.html), вы увидите, что есть 3 утечки:

1) PresidentDetailController.m, объект NSIndexPath * newPath (строка 75) никогда не освобождается 2) PresidentDetailController.m, объект UITextField * textField (строка 166) никогда не освобождается 3) PresidentsViewController.m, объект PresidentDetailController * childController (строка 86) никогда не освобождается

Тот, который вы предлагаете, не является утечкой; Ваши изменения в исходном коде являются причиной сбоя приложения. Использовать программу проверки Clang очень просто, взгляните на

http://clang.llvm.org/StaticAnalysisUsage.html#BasicUsage

С уважением

0 голосов
/ 18 мая 2009

Контроллер не освобождается, потому что self.controllers сохраняет его (коллекции, такие как NSArray, сохраняют помещенные в них объекты). Во втором блоке кода вы создаете полностью независимый объект, сразу же теряете его, а затем перезагружаете контроллер, который вы извлекаете из self.controllers (что приводит к вашей аварии).

Похоже, этот код намеревается удерживать свои контроллеры на протяжении всей жизни программы, так что это не так само по себе. Тот факт, что вы растете в памяти, предполагает, что вы создаете новые объекты. Я бы искал вызовы + alloc, + copy или -retain, для которых нет соответствующего вызова + autorelease или + release. В инструментах используйте инструменты ObjectAllocation и Leaks, чтобы определить конкретную память, которая была чрезмерно сохранена, и точку, в которой она создается. Точка создания не сообщает точно, где находится ошибка, но обычно это хороший совет.

Чтобы узнать схему развертки, которую вы здесь реализуете, вам нужно изучить пример кода SimpleDrillDown .

И, конечно, все студенты Какао должны передать Правила управления памятью близко к сердцу. Они не сложны, но они абсолютно необходимы для понимания. Я написал краткое изложение их , если это поможет.

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