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 的文档充其量是混乱的。那么,根据您的经验,我会得出结论,您应对两个对象的生命周期负责 - UIImage
和 CGImageRef
。最重要的是,您必须确保 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图像和内存的主要内容,如果未能解决你的问题,请参考以下文章