imageWithCGImage和内存

时间:2009-09-09 21:16:16

标签: cocoa-touch core-graphics

如果我使用[UIImage imageWithCGImage:],传入CGImageRef,我是否会释放CGImageRef或UIImage在解除分配后自行处理?

文档并不完全清楚。它说“这种方法不会缓存图像对象。”

最初我在将CGImageRef传递给CGImageRelease后调用了imageWithCGImage:,但是在模拟器中发出了malloc_error_break警告声称发生了双重免费。

8 个答案:

答案 0 :(得分:8)

根据fundamental rule of Cocoa memory management,拥有对象应该在不再需要时释放拥有的对象。其他对象负责自己获取和释放所有权。如果UIImage需要一个对象持久但不保留或复制它,那么这是UIImage实现中的一个错误,应该如此报告。

答案 1 :(得分:4)

我在Snow Leopard的XCode 3.2.1中遇到了同样的问题。我和Jason的代码几乎相同。

我查看了使用imageWithCGImage的iPhone示例代码,他们在调用CGImageRef后始终使用CGImageRelease发布imageWithCGImage

那么,这是模拟器中的错误吗?当我使用malloc_error_break时,我总是在控制台上收到CGImageRelease警告。

答案 2 :(得分:2)

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]不保证与传递给init方法的CGImage相同,因此该类会单独存储CGImage

答案 3 :(得分:0)

我同意你的观点 - 文档最适合此API。根据您的经验,我会得出结论,您要对两个对象的生命周期负责 - UIImageCGImageRef。最重要的是,您必须确保CGImageRef的生命周期至少与UIImage一样长(显而易见的原因)。

答案 4 :(得分:0)

你在Snow Leopard上使用Xcode 3.1吗?我遇到了同样的问题:

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会解决问题。

答案 5 :(得分:0)

<> 不是我的意见。我有同样的问题。根据文件

UIImage *image = [[UIImage alloc] initWithCGImage:imageRef];

imho保持所有参考文献的正确性。如果您使用的是CGDataProvider,请查看 CGDataProviderReleaseDataCallback 并在回调中设置断点。您可以看到在[发布]图像后正确调用,并且可以在那里释放()图像数据缓冲区。

答案 6 :(得分:0)

不确定这是否有帮助,但我遇到了类似的问题。 我阅读了答案,然后做了以下似乎已经解决的问题:

CGImageRef cgImage = [asset thumbnail];
    UIImage *thumbImage = [[UIImage imageWithCGImage:cgImage ]retain];
    UIImageView *thumbImageView = [[UIImageView alloc] initWithImage:thumbImage];
    CGImageRelease(cgImage);

我按照建议使用了自动释放,但这还不够。 一个我将图像添加到UIImageView然后我发布了cgImage 它没有崩溃并且很好地解除分配。为什么 - 我不知道但它有效。

顺便说一句,资产缩略图部分来自ALAsset库,您可能还需要其他东西。

答案 7 :(得分:0)

"This method does not cache the image object."

所以UIImage取得了所有权,因此你不应该释放CGImageRef。