UIImage выпущен, но CGImage не выпущен

Кажется, у меня проблема с управлением памятью, когда я создаю экземпляры UIImage, которые CGImages не выпускаются.

У меня есть пейджинг UIScrollView для прокрутки серии изображений в формате JPG. Ниже приведен весь мой класс, который представляет собой просмотр страницы в представлении прокрутки пейджинга.

Код запускается в основном потоке. В коде используется ARC. Я попытался загрузить изображения с помощью imageWithContentsOfFile: (возвращает объект с автореализацией), а также initWithContentsOfFile: (возвращает сохраненный объект). Я попробовал @autoreleasepool и использовал performSelectorOnMainThread, чтобы гарантировать, что код запускается в основном потоке, как это предлагается в других сообщениях.

При прокрутке изображения использование памяти увеличивается только до тех пор, пока приложение не будет завершено, как показано на скриншоте из инструментов. Обратите внимание на высокое выделение изображения io.

Скриншот, показывающий использование виртуальной памяти

Виртуальная память Tracker

На следующем скриншоте видно, что GTGImageScrollerPageViews, UIImageViews и UIImages освобождаются. Обратите внимание, что существуют объекты Transitory для этой нумерации в высоких 300-х годах. Однако CGImages не освобождаются, а количество живущих CGImages находится в высоких 400 и 0 Transitory.

Снимок экрана с указанием распределений

ассигнования

EDIT: Раньше я занимался переработкой и повторным использованием экземпляров GTGImageScrollerPageView в ScrollView, так как это общий шаблон для scrollviews, подобного этому. Чтобы упростить при попытке отладки этой проблемы, я разрешаю освободить весь GTGImageScrollerPageView после его отображения в ScrollView. Как вы можете видеть во втором изображении выше, есть только 4 жителя GTGImageScrollerPageView и 377 преходящих, есть также 388 UIImageViews и 389 UIIMages, перечисленных как преходящие, поэтому кажется, что UIImageViews и UIImages освобождаются от штрафа.

Если я вручную выпущу CGImage с CGImageRelease (прокомментировано в коде ниже), CGImages освобождаются. Я знаю, что я не должен этого делать, потому что я не владею CGImage, но это полезно для проверки того, что именно здесь возникает проблема. На скриншотах ниже показан тот же код, протестированный в Инструментах, но с CGImageRelease без комментариев.

Снимок экрана, показывающий использование виртуальной памяти с использованием CGImageRelease

Использование виртуальной памяти

Снимок экрана, показывающий распределения с использованием CGImageRelease

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

В профилирующих выводах, где используется CGImageRelease, вы можете видеть, что правильное количество объектов CGImage – это Living and Transitory, и эта память не растет неограниченно. Кроме того, приложение не сбой во время использования с использованием CGImageRelease.

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

Что здесь может вызвать этот неограниченный рост памяти?

Вот код для просмотра страницы

EDIT: В ответ на комментарии я обновил код, чтобы упростить его, тем самым устраняя отвлекающие факторы, такие как ivars и свойства, которые не нужны для демонстрации проблемы. Проблема остается неизменной, и при профилировании результаты одинаковы. Я также добавил в NSLog, который также выводит поток. Я вижу, что dealloc вызывается как ожидалось в GTGImageScrollerPageView, и он всегда является нитью # 1, и вызов displayAspectThumbImage всегда находится в потоке # 1.

Я действительно не верю, что что-то не так с кодом, который представлен здесь, и это подтверждается щедрым усилием Роба. Что-то еще вызывает это, но весь код, связанный с загрузкой и отображением изображения, находится здесь; здесь нет другого кода. Единственное замечательное, что я мог подумать о повышении, это то, что метод displayAspectThumbImage вызывается из scrollViewDidScroll и scrollViewDidEndDecellerating методов делегата scrollview, но тот факт, что методы вызываются в основном потоке, должен исключать проблемы автозавершения из-за запуска в другом потоке ,

Я проверил и NSZombies не включен, и нет никаких Зомби, увеличивающих использование моей памяти. Действительно, когда метод CGImageRelease называется, использование памяти довольно плоское, как видно на скриншоте выше.

@implementation GTGImageScrollerPageView - (void)dealloc { NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSThread currentThread]); } - (void)displayAspectThumbImage:(NSString *)path { NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSThread currentThread]); UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.bounds]; [self addSubview:imageView]; UIImage *image = [[UIImage alloc] initWithContentsOfFile:path]; [imageView setImage:image]; //If uncommented CGImages are disposed correctly //CGImageRelease([imageView.image CGImage]); } @end 

Протестировано:

iOS 6.1.4

iOS 5.0.1

3 Solutions collect form web for “UIImage выпущен, но CGImage не выпущен”

Очень жаль, что я сам отвечаю на этот вопрос, но подумал, что было бы полезно поделиться своим опытом.

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

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

Способ, которым я решил это, состоял в том, чтобы начать с моделирования сценария в новом проекте и обнаружил, что код не просачивался там. Затем я немного изменил код, и когда я переместил категории через утечку, появился.

Огромное спасибо Робу за его щедрые усилия, чтобы помочь мне в этом, и хотя он не предоставлял решение напрямую, общение с ним было действительно полезно для решения проблемы. Приятно знать, что там такие классные люди.

Я сделал простой бесконечный скроллер, используя ваш код, и после прокрутки почти 100 изображений использование памяти было, как и следовало ожидать, совершенно беспрецедентным:

ассигнования

В.М.

Глядя на ваш источник, я бы рекомендовал несколько мелочей (например, я бы поставил aspectImageView в расширение частного класса, а не на .h, я предполагаю, что вы устанавливаете pageIndex из вызывающей процедуры, но я бы добавил его как параметр displayAspectThumbImage , я бы сделал aspectImageView weak свойством и соответствующим образом aspectImageView код (например, создайте представление изображения, добавьте его как subview, затем установите свойство weak изображения для указания на этот объект) и т. д.), но ни один из них не имеет прямое отношение к вашей проблеме здесь.

Итог, ваша проблема не остается в коде, который вы нам поделили.

Попробуйте использовать свойство вместо ivar.

@property (неатомный, сильный) UIImageView * aspectImageView;

  • Квадратный миниатюра изображения UIImagePickerViewController
  • Изображение поворачивается на 90 градусов при использовании clipToMask
  • Поворот и обрезка UIImage
  • Решение Как анимация мусора
  • Преобразование NSData в CGImage, а затем обратно в NSData делает файл слишком большим
  • Пытаясь подрезать UIImage до соотношения сторон 1: 1 (квадрат), но он продолжает увеличивать изображение, вызывая его размытие. Зачем?
  • Обрезать UIImage альфа
  • Наложение камеры с помощью User-Photo не сохраняется как отредактировано
  • Ошибка утечки памяти CGImage памяти на iOS
  • Как выглядит правильный вызов CGImageCreate, если поставщик данных для него использует массив, созданный приложением?
  • Рисование гистограммы CGImage в Swift 3
  • Interesting Posts

    Проверка UITextField

    Имя набора изображений «xxx» используется несколькими наборами изображений с локализованным каталогом активов (.xcassets)

    Отключить методы делегирования в зависимости от версии iOS

    Как контролировать количество одновременных касаний в представлении в iOS

    Не удается найти объявление протокола для «MFMailComposeViewControllerDelegate»; Вы имели в виду «UIPageViewControllerDelegate»?

    Прикрепите фотографию к письму из приложения iPhone

    Как добавить изображение с эффектом параллакса выше заголовка UITableView и сохранить заголовок липким

    SKStoreProductViewController отображает приложения от разработчика

    Как использовать статическую библиотеку (например, библиотеку cocoapods) на XCTest?

    временная задержка при сохранении строк в Core Data?

    Как программировать обнаружение, если iCloud включен на устройстве пользователя, когда используется только NSUbiquitousKeyValueStore?

    Что означает NSMakeRange (i, 1)?

    MagicalRecord не сохраняет данные

    Получить идентификатор пакета из файла p12 / pem

    Как установить значение по умолчанию для UIPickerView

    PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.