Память iPhone не освобождается после выгрузки view и освобождения, почему?

#iphone #objective-c #memory-management

#iPhone #objective-c #управление памятью

Вопрос:

Я уже несколько недель борюсь с проблемами с памятью в своем приложении для iPhone и пока не смог решить проблему, несмотря на всесторонние исследования в Интернете.

Вот в чем дело: мое приложение взаимодействует с API Google Analytics и основано на 3 основных представлениях: основном представлении, представлении настроек и представлении в виде таблицы, в котором представлены данные из Google (с пользовательской ячейкой). Я также создал пользовательский класс, который извлекает данные из Google, а затем убивает себя по завершении. Все данные хранятся в едином центре обработки данных.

Все представления инициируются, а затем освобождаются следующим образом:

 if (self.vVisitsTabelView == nil) {
    visitsTabelView *initiatevisitsTabelView = [[visitsTabelView alloc]     initWithNibName:@"visitsTabelView" bundle:nil];
    self.vVisitsTabelView = initiatevisitsTabelView;
    [initiatevisitsTabelView release];
}

[self.navigationController  pushViewController:vVisitsTabelView animated:YES];
[vVisitsTabelView release];
vVisitsTabelView = nil;
  

Проблема в том, что при каждой загрузке view память увеличивается, но когда view открывается, он не освобождает память, хотя вызывается dealloc и освобождаются ВСЕ переменные экземпляра. Этот цикл повторяется снова и снова (при повторной загрузке того же представления), и потребление памяти становится очень высоким. После требовательного использования я даже получил 200 МБ реальной памяти и 320 виртуальной на инструментах. Как ни странно, предупреждение о памяти было получено только один раз, однако мое приложение никогда не зависало из-за нехватки памяти, и приборы не указывают на ОТСУТСТВИЕ утечек.

После входа в фоновый режим память медленно освобождается и используется другими приложениями, однако, когда я возвращаюсь на передний план, память восстанавливается до уровня перед входом в фоновый режим (возможно, формирует виртуальную память?). Этот процесс занимает 9 секунд, и за это время приложение зависает.

Есть идеи, как справиться с этой ситуацией? Я искал везде и тщательно следовал всем рекомендациям.

Любая зацепка высоко ценится…

Пожалуйста, извините меня, если я не следовал рекомендациям, я впервые в этом замечательном месте.

Ответ №1:

Спасибо, не могли бы вы подробнее рассказать, как это сделать?

Да; у вас утечка памяти. Теперь инструмент утечки может или не может сообщить вам, что происходит утечка. Он не будет обнаруживать объекты, которые все еще каким-то образом связаны с остальной частью приложения; т.Е. Если ссылка на объект сохраняется в NSMutableDictionary где-то, который все еще используется приложением, он не будет обнаружен.

Поскольку вы точно знаете, какой объект подвергается утечке, необходимо выяснить, что его сохранило, но не освободило. Инструмент распределения обеспечивает именно эту возможность. В частности, вы можете настроить инструмент распределения для отслеживания количества сохранений.

Эта статья может помочь http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-to-find-undesirable-memory-growth/.

Кроме того, существует ряд очень похожих вопросов / ответов на SO, которые касаются этого. За последние пару недель я не могу найти один, который дал отличное наглядное руководство о том, как делать именно то, что вы хотите.

Комментарии:

1. Спасибо! теперь вы предоставили мне несколько планов на выходные 😉

Ответ №2:

Вы проверили количество сохранений в своих просмотрах? [Просмотр retainCount] сделает это.

В любом случае вам следует настоятельно рассмотреть возможность перехода на ARC, который является новым для iOS5. Вы должны быть в состоянии попрощаться со всеми своими проблемами управления памятью.

Комментарии:

1. Большое спасибо за ваш быстрый ответ… Повлияет ли переход на ARC на совместимость с более старыми версиями IOS? допустим, IOS 3.3?

2. ARC можно использовать только на iOS 4.3 и выше, поэтому вам придется отказаться от поддержки iOS3 и более старых версий iOS4.

3. Значение retainCount бесполезно. Используйте инструмент распределения, чтобы определить, что сохранило, но не освободило объект.

4. Спасибо, не могли бы вы подробнее рассказать, как это сделать?