Проблемы с управлением памятью, автовыпуском, постоянная куча иногда 250+ кб на iOS

Я действительно рву на себе волосы, кажется, у меня серьезные проблемы с управлением памятью в приложении для iOS.

Вот случай: сначала я загружаю таблицу. Когда пользователь нажимает на ячейку, она представляет собой сложный вид. Наибольшее потребление памяти в представлении связано с тем, что оно загружает 20+ UIImages 500x500. В этом представлении есть еще две вкладки, загружающие список медиа (эти UIImage, но затем в виде таблицы) и еще одна простая таблица.

Когда я возвращаюсь к первому представлению таблицы, очевидно, что в куче все еще выделено более 250 КБ. Я знаю, что вид сложен, но нет причин сохранять так много памяти. И угадайте, что, когда я часто переключаюсь на представление, в конце концов у приложения заканчивается память, и оно закрывается.

Что я пытался решить:

  • Исправьте все проблемы с анализом, чтобы больше не было утечек.
  • Снова проверьте все init на освобождение, используя autorelease, где это возможно.
  • Проверка всех утечек памяти с помощью Инструменты -> Утечки. За время выполнения 6 я получаю не более 2-3 утечек.
  • Наконец, Инструменты -> Распределение, проверка кучи. Вот что меня смущает, между двумя отмеченными хипшотами получается разница в 250+ кБ. Я изучил это, используя подробные представления. Я не могу понять это: когда он указывает на один из моих методов/классов, я почти уверен, что все там либо выпущено, либо автоматически выпущено. Это также указывает на множество не моих (скажем, QuartzCore) методов/классов.

Кроме того, я не понимаю, почему autorelease не выпускается автоматически. Я имею в виду, иногда это выглядит так, как будто объект, помеченный для автоматического выпуска, выпущен слишком поздно. Я сам не создавал NSAutoreleasePool, поэтому возможно ли, что пул сливается только тогда, когда среда выполнения останавливается? Как можно периодически сливать пул (даже если он не мой).

Любая помощь приветствуется.

С уважением,

Рейндер

Используется для проверки кучи: http://www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak-using-heapshot-analysis-найти-нежелательный-рост-памяти/


person Reinder de Vries    schedule 17.01.2012    source источник


Ответы (2)


Я думаю, что вы, возможно, захотите сначала попытаться оптимизировать свой дизайн и прочитать руководства по эффективному управлению памятью. Лучшее понимание компонентов и среды выполнения поможет не только в отслеживании распределения памяти, но и облегчит поиск утечек.

  • Во-первых, вы всегда должны использовать release. Используйте autorelease только при необходимости.
  • Убедитесь, что вы следуете рекомендациям по реализации UITableView и эффективному управлению UITableViewCells (отложенная загрузка, повторное использование ячеек и т. д.).
  • Проверьте, есть ли у вас циклы сохранения (сохраненные контроллеры представления не будут освобождены).
  • Отслеживайте освобождение ваших контроллеров представления и объектов
  • Не храните в памяти то, что вам больше не нужно.
  • Не загружайте то, что вам сейчас не нужно.
person CodeStage    schedule 17.01.2012
comment
Хорошо, я попробовал ARC, и утечки памяти остались. Я думаю, что вся проблема в этих циклах сохранения. Строгие ссылки между объектами, которые никогда не освобождаются. Как я могу обойти это? Из: stackoverflow.com/questions/6260256/ - person Reinder de Vries; 17.01.2012
comment
Я почти уверен, что это циклы сохранения. Я читаю о расширенном управлении памятью Apple и, не хочу этого признавать, я создал ссылки между классами, такими как Document ‹-> Page и Page ‹-> Document. Спасибо за совет, и обратно к чертежной доске ;-). См.: developer.apple.com/library /mac/#documentation/Cocoa/Conceptual/ - person Reinder de Vries; 17.01.2012
comment
Хорошо, чтобы быть окончательным. Дочерние классы (например, Page) должны иметь слабую ссылку на своих родителей (Document). Родительские классы (Document) должны иметь сильную ссылку на своих дочерних (Page). Сильная ссылка в моем случае напоминает (неатомарное, сохраняемое) свойство, а слабая ссылка напоминает (назначаемое) свойство. Я использовал объекты, подобные делегатам, для уведомления родительского объекта, используя (неатомарное, сохранение). Я думаю, что это должно быть @property (назначить). Будущим поколениям: знайте, что вы сохраняете/отпускаете. - person Reinder de Vries; 17.01.2012

Используете ли вы imageNamed для загрузки изображений — этот метод сохранит все изображения в кэше памяти. Вместо этого попробуйте initWithContentsOfFile.

Будьте осторожны; initWithContentsOfFile: вообще не кэшируется, поэтому, если вы часто используете этот метод для одного и того же изображения, вам следует использовать imageNamed:!

person deanWombourne    schedule 17.01.2012
comment
Нет, но спасибо за ответ. Все изображения загружаются из ~/Documents с использованием подкласса UIImage, который использует initWithImage, который получает +UIImage imageWithContentsOfFile. - person Reinder de Vries; 17.01.2012