(iphone) 从图像创建新图像时是不是会造成泄漏?
Posted
技术标签:
【中文标题】(iphone) 从图像创建新图像时是不是会造成泄漏?【英文标题】:(iphone) am I creating a leak when creating a new image from an image?(iphone) 从图像创建新图像时是否会造成泄漏? 【发布时间】:2011-01-08 15:24:27 【问题描述】:我有以下代码作为 UIImage+Scale.h 类别。
-(UIImage*)scaleToSize:(CGSize)size
UIGraphicsBeginImageContext(size);
[self drawInRect:CGRectMake(0, 0, size.width, size.height)];
// is this scaledImage auto-released?
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
我使用如上获得的图像并使用它如下。
UIImage* image = [[UIImage alloc] initWithData: myData];
image = [image scaleToSize: size]; <- wouldn't this code create a leak since
image(before scaling) is lost somewhere?
如果图像首先使用自动发布创建,我猜上面的代码可以正常工作。 但是,如果图像是使用“alloc”创建的,那么它会在我的短知识中造成泄漏。
我应该如何更改 scaleToSize: 以防它?
谢谢
编辑-我想在 UIImage 上使用分配(或保留)/释放,以便我可以将 UIImage 的数量保持在内存中较小的一点。 (我正在循环加载许多 UIImages 设备无法接受)
【问题讨论】:
【参考方案1】:请注意,您的代码可以重写为:
UIImage *image = [[UIImage alloc] initWithData:myData];
UIImage *scaledImage = [image scaleToSize:size];
image = scaledImage;
让我们看看会发生什么:
image
是通过alloc
获得的,因此您拥有该对象
scaledImage
是通过返回自动释放对象的方法获得的,因为UIGraphicsGetImageFromCurrentImageContext()
返回一个自动释放对象
您拥有原始的image
,但您不拥有scaledImage
。你负责发布原image
,否则有泄密。
在您的代码中,您使用一个变量来引用两个对象:原始图像和缩放图像。这不会改变您拥有第一张图片的事实,因此您需要释放它以避免泄漏。由于使用相同的变量会丢失原始图像引用,因此一种常见的用法是将-autorelease
发送到原始对象:
UIImage *image = [[[UIImage alloc] initWithData:myData] autorelease];
image = [image scaleToSize:size];
或者,如果您宁愿释放原始图像而不是自动释放它,
UIImage *image = [[UIImage alloc] initWithData:myData];
UIImage *scaledImage = [image scaleToSize:size];
[image release];
// use scaledImage from this point on, or assign image = scaledImage
IMO,更改 scaleToSize:
没有意义。它是一种基于给定UIImage
实例创建(自动发布的)图像的实例方法。它类似于-[NSString stringByAppendingString:]
,它基于给定的NSString
实例创建一个(自动释放的)字符串。它不会也不应该关心原始字符串的所有权,这同样适用于您的 scaleToSize:
方法。该方法如何知道调用者是否要保留原始图像?
我还将 scaleToSize:
重命名为 imageByScalingToSize
以使其类似于 Cocoa 的命名约定 — 您通过对现有图像应用操作来获取图像。
【讨论】:
自从我修改图像以来,大多数时候,我想更改图像本身,而不是创建新图像。我希望改变 scaleToSize: 。我最近意识到 UIImage 是相当大的内存消耗者,并且希望保持内存中 UIImage* 的数量很小。或者至少,使用 alloc/release 而不是 autorelease。UIImage
是不可变的。你不能简单地改变它。而且,除非您同时创建多个图像,否则使用自动释放池与手动发送 -release
并没有太大区别。我会更新帖子告诉你如何使用-release
而不是-autorelease
。
感谢 Bavarious,是的,我正在同时创建许多图像,并且想自己处理内存释放。
谢谢。根据您的建议,我最终使用了分配/释放并在必要时创建了自动释放池/释放池。关于 UIImage 不可变的信息也有很大帮助。【参考方案2】:
是的,你肯定有泄漏。之前存储在图像中的对象不再被引用,但尚未释放
【讨论】:
以上是关于(iphone) 从图像创建新图像时是不是会造成泄漏?的主要内容,如果未能解决你的问题,请参考以下文章
PDFbox 1.7.0 - 如何在使用PDFBox添加新图像时保留现有图像?
当发布新图像时,确保图像不会在客户端浏览器中兑现的最佳方法是啥?