Как найти реальную причину предупреждения памяти и как ее разрешить в приложении iOS

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

Основные сведения, которые вы должны знать о приложении:

  • Мы разработали приложение для iPad. В этом случае мы должны использовать в некоторых случаях более 2000 изображений, поэтому при запуске приложения мы не хотим показывать им изображение-заполнитель (требование клиента). Для этого мы использовали SDWebImage, сохраняли изображения на диске и позже чем мы загружаем изображения оттуда.

  • Есть так много основных анимаций, которые я выполнял как "эффект Gennie", всплывающие окна и так много других основных анимаций.

Мы использовали ARC в нашем проекте, и мы обнаружили, что из-за непредвиденного сбоя приложения сбой памяти.

Мы использовали Инструменты "Распределение" для поиска грязной памяти.

Раньше мы анализировали журналы, и мы сохраняли изображения с помощью SDWebImage в DISK, он разрешает частое сбой приложения, но все же приложение сбой из-за предупреждения о памяти.

Когда мы углубимся в то, что мы обнаружили, что "Анонимная VM" продолжает включать и не выпускать память, когда какой-либо экранный переключатель в iPad.

Вот скриншот профилирования нашего приложения на устройстве.

введите описание изображения здесь

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

Любая помощь будет оценена. Спасибо.

Ответ 1

Попробуйте Infer, это может быть полезно, оно сообщает о проблемах с утечкой памяти в iOS и C-коде.

Статический анализатор при развертывании в Facebook, где он используется как часть процесса разработки мобильных приложений. Infer нацеливает критические ошибки, такие как исключения нулевого указателя, утечки ресурсов и утечки памяти - проблемы, которые приводят к сбоям или ухудшению производительности в приложениях.

Ответ 2

Похоже, что какой-то объект в вашем приложении не освобождается, вероятно, из-за цикла сохранения. Проверить ссылки на делегаты - это слабые ссылки. Также проверьте блоки и убедитесь, что сильная ссылка на self не зафиксирована в блоке. Если Object A сохраняет сильную ссылку на Object B, то передает блок, содержащий сильную ссылку на self на объект B, оба объекта потенциально блокируются в цикле сохранения. Используйте этот синтаксис, чтобы передать слабую ссылку на self:

 __weak typeof(self)weakSelf = self;

[doSomethingWithBlock:^() {
    __strong typeof(weakSelf)strongSelf = weakSelf;
    if (!strongSelf) {
        return;
    }
    [strongSelf doSomething];}];

в Swift выполните следующее:

someObject.doSomething() { [weak self] in
                    self?.doSomething()
                }

или использовать [unowned self] - оба создают слабую ссылку на self, в случае [слабого self], self является необязательным

Чтобы все ваши объекты были освобождены как ожидалось, поместите оператор журнала в свои функции dealloc/deinit и проверьте, действительно ли они вызываются.

Ответ 3

Росомаха,

Не сказать, что это абсолютный ответ на ваш вопрос, но может дать вам некоторый намек на решение проблемы.

Мой случай:

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

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

Я никогда не проверял, вызван ли мой viewController dealloc или нет. Поставив точку останова в dealloc, я понял, что dealloc никогда не вызывался (по разным причинам, которые я разрешил сейчас).

Как и в вашем случае, мой chatViewController, хотя и не загружал 100 изображений, используемых для загрузки 8 - 10 изображений за раз, и крах начал появляться, когда я использовал панорамные изображения, а не обычные изображения.

Вывод:

  • Мой viewController имел сильную ссылку на UIImageView, который загружал тяжелые изображения, и поскольку dealloc никогда не вызывался для моего ViewController, все загруженные изображения никогда не выполнялись, что приводило к сбою памяти.

  • Когда я загружал тяжелые изображения, я выполнял несколько расчетов, чтобы уменьшить размер изображения. Большинство вычислений включало повторное создание изображения из NSData с использованием UIImageJPEGRepresentation. Повторное распределение данных и переменной владельца изображения добавляется к потреблению памяти приложения.

  • Поскольку мой ViewController участвовал в количестве вызовов API, я создал класс справочной службы singleton, к которому я использовал пропускающие блоки соответствия, и я не использовал его самостоятельно в завершающих блоках, переданных методам. Что на самом деле способствовало увеличению количества ссылок ARC и никогда не позволяло моему контроллеру просмотра освободиться.

Способ отладки

  • Как вы уже упомянули в своем вопросе о том, что вы загружаете множество изображений в свой ViewController, убедитесь, что viewController правильно освобожден и освобождает всю память, загруженную всем ImageView, присутствующим в ViewController.

  • Если ваш ViewController dealloc не будет вызван, то как способ проверки (помните не о решении) в viewWillAppear установите для всех свойств изображения imageView значение nil и принудительно очистите загруженную память.

  • Если ViewController dealloc не получает вызов, оказывается виновником, попробуйте найти, где вы отправляете себя как сильную ссылку. Если найдено, попробуйте использовать weak self.

Я знаю, что это не абсолютный ответ на ваш вопрос. Просто поделитесь своим опытом с вами. Надеюсь, это по крайней мере даст вам подсказку, чтобы решить вашу проблему.

Ответ 4

В WWDC 2012 Сессия 242 Производительность приложений iOS: память, Apple представляет способ обнаружения проблемы памяти с помощью шаблона Allocations инструментов, начиная с 31 мин.

1. Heap SnapsShots
Apple предлагает повторно нажать pop, прежде чем сделать снимок кучи, я предпочитаю push pop только один раз.

Кнопка "Снимок" называется "Mark Generation"
Кнопка моментального снимка

Вы должны сделать снимок несколько раз.

2. Рост памяти

Если ваша память растет между каждым снимком, вы можете выкопать один из снимков, кроме первого.

введите описание изображения здесь

Сортировка объектов Persitent, вероятно, вы видели вашу проблему ViewController (если вы только нажимаете pop-команду один раз). Или вы можете просто ее искать.

persitent

3. Теперь вы можете копаться в дереве вызовов, находить и исправлять проблемы.

4. Вы можете использовать эту технику не только для push pop viewControllers, но также прокручивать в tableView, выполнять поиск базы данных и любые другие случаи.