imageWithCG图像和内存

Posted

技术标签:

【中文标题】imageWithCG图像和内存【英文标题】:imageWithCGImage and memory 【发布时间】:2009-09-09 21:16:15 【问题描述】:

如果我使用[UIImage imageWithCGImage:],传入CGImageRef,然后释放CGImageRef 还是UIImage 在释放时自行处理?

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

最初我在将 CGImageRef 传递给imageWithCGImage: 后调用了CGImageRelease,但这导致模拟器中出现malloc_error_break 警告,声称正在发生双释放。

【问题讨论】:

我建议在bugreport.apple.com 提交文档错误,要求他们澄清这一点。 【参考方案1】:

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

【讨论】:

【参考方案2】:

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

我查看了使用imageWithCGImage 的iPhone 示例代码,他们总是在调用imageWithCGImage 后使用CGImageRelease 释放CGImageRef

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

【讨论】:

这应该是对 Jason 的回答的评论,或者是一个新问题,因为 SO 不是论坛。 我无法评论其他人的帖子,因为我没有足够的“声誉”。此外,这不是一个新问题。我只是建议问题可能只发生在模拟器中,而不是设备上。【参考方案3】:

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

由于-[UIImage CGImage]属性返回的CGImage不能保证与传入init方法的CGImage相同,所以类单独存储CGImage

【讨论】:

【参考方案4】:

我同意你的看法——这个 API 的文档充其量是混乱的。那么,根据您的经验,我会得出结论,您应对两个对象的生命周期负责 - UIImageCGImageRef。最重要的是,您必须确保 CGImageRef 的生命周期至少与 UIImage 一样长(原因很明显)。

【讨论】:

【参考方案5】:

您是否在 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 会解决这个问题。

【讨论】:

从 Xcode 8.1 开始,这对我有用。如果我不释放CGImage,我会发生内存泄漏,所以我认为这是这样做的方法。【参考方案6】:

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

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

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

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

【讨论】:

似乎您在这里泄漏了 thumbImage,除非您在其他地方发布它。 UIImageView.initWithImage:会保留图片。【参考方案7】:

不是我的意见。我有同样的问题。根据文档

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

恕我直言,所有参考资料均正确无误。如果您使用的是 CGDataProvider,请查看 CGDataProviderReleaseDataCallback 并在回调中设置断点。您可以看到在您 [release] 图像后正确调用了它,并且您可以在此处释放()您的图像数据缓冲区。

【讨论】:

【参考方案8】:
"This method does not cache the image object."

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

【讨论】:

以上是关于imageWithCG图像和内存的主要内容,如果未能解决你的问题,请参考以下文章

在 UITesting 期间导致内存警告和崩溃的背景图像

JavaFX - 加载图像和内存问题

从内存中读取图像,知道指向内存的指针。 VC++ [关闭]

内存使用和操作图像

异步上传和调整多个图像大小时出现内存不足异常

ipad:图像加载和内存管理问题以及应用程序崩溃