ImageWithCGImage и память
Если я использую [UIImage imageWithCGImage:]
, передавая в CGImageRef
, то я освобождаю CGImageRef
или UIImage позаботится об этом сам, когда он будет освобожден?
Документация не совсем понятна. В нем говорится: "Этот метод не кэширует объект изображения".
Изначально я вызывал CGImageRelease
в CGImageRef после передачи его в imageWithCGImage:
, но это вызвало предупреждение malloc_error_break
в симуляторе, утверждающее, что происходит двойное освобождение.
Ответы
Ответ 1
Я согласен с вами - документация в лучшем случае запутана для этого API. Исходя из вашего опыта, я бы пришел к выводу, что вы отвечаете за время жизни обоих объектов - UIImage
и CGImageRef
. Кроме того, вы должны убедиться, что срок службы CGImageRef
не меньше, чем UIImage
(по очевидным причинам).
Ответ 2
В соответствии с основным правилом управления памятью Cocoa, объект-владелец должен освободить принадлежащий ему объект, когда он ему больше не нужен. Другие объекты несут ответственность за принятие и освобождение собственности самостоятельно. Если a UIImage
требуется, чтобы объект сохранялся, но не сохранял и не копировал его, это ошибка в реализации UIImage
и должна сообщаться как таковая.
Ответ 3
У меня такая же проблема в XCode 3.2.1 на Snow Leopard. У меня почти такой же код, как у Джейсона.
Я просмотрел образец кода iPhone, который использует imageWithCGImage
, и они всегда выпускают CGImageRef
с помощью CGImageRelease
после вызова imageWithCGImage
.
Итак, это ошибка в симуляторе? Я всегда получаю предупреждение malloc_error_break
на консоли, когда я использую CGImageRelease
.
Ответ 4
Владение в UIImage
около CGImage
неясно. Похоже, не копируйте CGImage
, но он не гарантируется документацией. Поэтому мы должны справиться с этим сами.
Я использовал новый подкласс UIImage
для решения этой проблемы. Просто сохраняя прохождение CGImage
и высвобождая его, когда dealloc
.
Вот пример.
@interface EonilImage : UIImage
{
@private
CGImageRef sourceImage;
}
- (id)initWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation;
@end
@implementation EonilImage
- (id)initWithCGImage:(CGImageRef)imageRef scale:(CGFloat)scale orientation:(UIImageOrientation)orientation
{
self = [super initWithCGImage:imageRef scale:scale orientation:orientation];
if (self)
{
sourceImage = imageRef;
CGImageRetain(imageRef);
}
return self;
}
- (void)dealloc
{
CGImageRelease(sourceImage);
[super dealloc];
}
@end
Поскольку свойство CGImage
, возвращаемое свойством -[UIImage CGImage]
, не может быть таким же CGImage
, переданным в метод init, класс сохраняет CGImage
отдельно.
Ответ 5
Используете ли вы Xcode 3.1 на Snow Leopard? Я испытываю одну и ту же проблему:
CGContextRef ctx = ...;
CGImageRef cgImage = CGBitmapContextCreateImage(ctx);
UIImage * newImage = [[UIImage imageWithCGImage:cgImage] retain];
CGImageRelease(cgImage); // this should be OK, but it now crashes in Simulator on SL
Я предполагаю, что обновление до Xcode 3.2 устранит проблему.
Ответ 6
< > Не мое мнение. У меня такая же проблема. Согласно документации
UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];
imho сохраняет правильность всех ссылок. Если вы используете CGDataProvider, пожалуйста, взгляните на
CGDataProviderReleaseDataCallback
и установите контрольную точку в своем обратном вызове. Вы можете видеть, что это правильно вызывается после того, как вы [отпустите] свое изображение, и вы можете освободить() свой буфер данных изображения там.
Ответ 7
Не уверен, что это помогает, но у меня была аналогичная проблема.
Я прочитал ответы, а затем сделал следующее, которое, похоже, исправило его:
CGImageRef cgImage = [asset thumbnail];
UIImage *thumbImage = [[UIImage imageWithCGImage:cgImage ]retain];
UIImageView *thumbImageView = [[UIImageView alloc] initWithImage:thumbImage];
CGImageRelease(cgImage);
Я использовал автореферат, как было предложено, но этого было недостаточно.
Один я добавил изображение в UIImageView, а затем выпустил cgImage.
Это не сработало и прекратилось. Почему? Я понятия не имею, но это сработало.
Элемент миниатюры объекта из библиотеки ALAsset, кстати, вам может понадобиться что-то еще.
Ответ 8
"This method does not cache the image object."
Итак, UIImage берет на себя ответственность, и поэтому вы не должны выпускать CGImageRef.