Предупреждение о памяти и сбой: как с этим справиться

Я использую инструменты, чтобы увидеть утечки памяти. По крайней мере, в одном сценарии, когда я постоянно пролистываю слайды / страницы (внутри UIScrollView), я не вижу утечки памяти. Используя инструменты - в разделе «Срок службы распределения» Я переключаюсь на просмотр «Создано и все еще жив» и вижу, что объем памяти составляет около 1,17 МБ. Я предполагаю, что это означает, что мое приложение использует только этот объем фактической памяти, а остаток правильно перерабатывается.

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

Если я не использую много памяти и не имею утечки памяти, почему я получил память предупреждение? Поскольку я ничего не могу выпустить, я не вижу способа избежать сбоя. Кто-нибудь сталкивался с этой ситуацией или знает, что я могу сделать? Я неправильно интерпретирую что-нибудь из Instruments? Большое спасибо за любой комментарий.

7
задан Peter Hosey 6 March 2010 в 22:19
поделиться

3 ответа

В документации говорится:

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

Таким образом, каждое изображение, которое вы загружаете с помощью imageNamed: , будет продолжать существовать в кэше после того, как вы освободите свое последнее право собственности на него.

Инструменты не показывают это как утечку, потому что, строго говоря, это не так: кое-что (UIImage) все еще знает об этих изображениях. Инструмент Leaks покажет только утечку для объекта, который существует, но ничего не знает о нем.

Однако вы все еще можете увидеть это в инструментах.

  1. Выберите инструмент ObjectAlloc в документе трассировки и отсортируйте список классов по текущему количеству или по текущему общему размеру. Вы увидите, что большая часть памяти занята объектами UIImage.
  2. Если навести указатель мыши на столбец имени класса для строки UIImage, вы увидите значок ➲ (перейти в iTunes-Store); если вы нажмете на это, вы увидите список всех ваших экземпляров UIImage.
  3. Затем, если навести указатель мыши на столбец адреса для строки экземпляра, вы увидите ту же кнопку; на этот раз щелкнув по нему, вы перейдете к истории этого адреса, включая все создание, сохранение, выпуск и освобождение объектов с этим адресом.

    Здесь вы можете увидеть распределение изображения (в классе UIImage, упорядоченное вами на несколько кадров вниз), удержание (вами) и освобождение (вами). Вы также можете видеть, что он не был выпущен UIImage - кэш + [UIImage imageNamed:] по-прежнему владеет изображением, отсюда и «утечка».

Если вы не хотите, чтобы изображения накапливались подобным образом, загрузите их самостоятельно, используя imageWithContentsOfFile: и метод - [NSBundle pathForResource: ofType:] ].

ОБНОВЛЕНИЕ: Я читал, что начиная с iOS 3, UIImage будет очищать свой кеш (по крайней мере, в некоторых) ситуациях с нехваткой памяти, так что это не должно быть такой большой «утечкой», как раньше. Вы, вероятно, по-прежнему будете видеть скопление памяти, но в конечном итоге вы увидите, что куча рушится.Если вы все еще видите скопление памяти и можете доказать, что это вина Apple, вам следует задокументировать свои доказательства и зарегистрировать ошибку .

11
ответ дан 6 December 2019 в 14:03
поделиться

Установлено ли для переменной среды NSZombieEnabled значение yes? Это приведет к тому, что освобожденные объекты останутся в памяти, что не позволит вам восстановить память. Так что попробуйте отключить его, если он активен.

2
ответ дан 6 December 2019 в 14:03
поделиться

Обнаружен источник проблемы. Это в следующем фрагменте

UIImage *image = [UIImage imageNamed:imageFile];

cartoon = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 40.0, 320, 280)];

cartoon.image = image ;
cartoon.backgroundColor = [UIColor brownColor];

. У меня есть сотни изображений плюс некоторый текст на каждой странице, и пользователь может пролистывать их, щелкая пальцем (точно так же, как в приложении для фотографий iphone). Я создаю только 3 страницы в своем UIScrollView и загружаю / выгружаю (а также освобождаю) все, что я явно выделил. Поэтому, когда дело доходит до выпуска мультфильма, я просто выпускаю мультфильм UIImageView, а не UIImage, думая, что он будет выпущен автоматически.

Но похоже, что он не выпускается автоматически. Мое приложение получает предупреждение о памяти (я не предпринимаю никаких действий), и ОС выгружает мои представления, вызывая сбой.

Когда я закомментирую две строки (измененный фрагмент ниже), проблема исчезнет. Никаких предупреждений, никаких сбоев.

    //UIImage *image = [UIImage imageNamed:imageFile];

cartoon = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 40.0, 320, 280)];

//cartoon.image = image ;
cartoon.backgroundColor = [UIColor brownColor];

Кто-нибудь знает, как обойти эту проблему? Есть ли способ принудительно освободить память из UIImage при появлении предупреждения?

0
ответ дан 6 December 2019 в 14:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: