- [UIImage drawInRect:] / CGContextDrawImage () не освобождает память? - PullRequest
3 голосов
/ 03 июня 2010

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

- (UIImage *) blendedImageOn:(UIImage *) backgroundImage  {
 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 UIGraphicsBeginImageContext(backgroundImage.size);

 CGRect rect = CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height);
 [backgroundImage drawInRect:rect];
 [self drawInRect:rect];
 UIImage* blendedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];

 UIGraphicsEndImageContext();
 [pool release];

 return [blendedImage autorelease];
}

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

Сеанс Instruments показал, что вызовы malloc, вытекающие из вызовов drawInRect: отвечают за большую часть использования памяти. Я попытался заменить drawInRect: сообщения эквивалентными вызовами функций для функции CGContextDrawImage, но это не помогло. AutoReleasePool был добавлен после того, как я обнаружил проблему использования памяти; это также не имело значения.

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

- Редактировать 1: спасибо за комментарии. Метод вызывается в методе контроллера, который устанавливает 20 представлений, поэтому в цикле у меня есть следующий вызов:

    UIImage *blendedImage = [newImage blendedImageOn:backgroundImage];

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

- Изменить 2: И да, я пытался добавить пул автоматического выпуска перед вызовом blendedImageOn: также безрезультатно.

- Правка 3: исправлена ​​смущающая ошибка UIImage, выпускаемого из-за пула автоматического выпуска. Назначение пула автоматического выпуска состоит в том, чтобы выпустить любые объекты , кроме результата UIImage, в случае, если избыточная память вызвана временными объектами, добавленными в основной пул автоматического выпуска, которые не освобождаются немедленно.

Вопрос, который я пытался задать (очень плохо, я признаю!), Таков: почему 20-кратный вызов этого метода приводит к большому использованию памяти?

Ответы [ 4 ]

1 голос
/ 09 июня 2010

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

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

1 голос
/ 03 июня 2010

Вы не должны вызывать drawRect: метод напрямую. используйте [self setNeddsDisplay]; вместо этого (это не поможет вам с этой утечкой);

О вашей утечке. удалить все о пуле. Ваш метод возвращает автоматически выпущенный объект UIImage. Пожалуйста, вставьте код, который вы используете, вернул UIImage, и я смогу вам помочь. Очень вероятно, что вы должны создать пул там, где вы вызываете blendedImageOn:, и сливать пул каждые 3-5 итераций.

0 голосов
/ 14 сентября 2010

В соответствии с правилами использования памяти iPhone любой метод, который возвращает «принадлежащий» объект (не автоматически выпущенный), должен начинаться с «alloc» или «new», или он должен содержать «copy».

Ваше имя "blendedImageOn" не соответствует этим правилам. Если вы используете его через месяц или кто-то другой, вы не помните, что изображение сохраняется внутри, и у вас будет утечка памяти.

0 голосов
/ 03 июня 2010

Одна проблема с вашим кодом состоит в том, что полученный вами объект blendedImage помечается для автоматического выпуска, а когда вы освобождаете временный пул автоматического выпуска, poof, вы также освобождаете blendedImage.

Вы можете сохранить до тех пор, пока пул не будет освобожден, а затем вернуть его автоматически освобожденным:

...
UIImage* blendedImage = UIGraphicsGetImageFromCurrentImageContext(); 

UIGraphicsEndImageContext();
[blendedImage retain];       // keep this past pool release
[pool release];

[blendedimage autorelease];  // now it will be autoreleased from the main pool

return [blendedImage release];  // release to balance out the retain above
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...