- [UIImage drawInRect:] / CGContextDrawImage()不释放内存?

时间:2010-06-02 21:35:16

标签: iphone memory-management uiimage

我想轻松地将UIImage混合到另一个背景图像之上,因此为UIImage写了一个类别方法,改编自blend two uiimages based on alpha/transparency of top image

- (UIImage *) blendedImageOn:(UIImage *) backgroundImage  {
 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 UIGraphicsBeginImageContext(backgroundImage.size);

 CGRect rect = CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height);
 [backgroundImage drawInRect:rect];
 [self drawInRect:rect];
 UIImage* blendedImage = [UIGraphicsGetImageFromCurrentImageContext() retain];

 UIGraphicsEndImageContext();
 [pool release];

 return [blendedImage autorelease];
}

不幸的是,我的应用程序使用上述方法加载大约20个图像并将它们与背景和光泽图像混合(因此可能大约40个调用),正在设备上被抛弃。

一个Instruments会话显示,对来自drawInRect:的调用的malloc调用负责大量的内存使用。我尝试用函数CGContextDrawImage的等效函数调用替换drawInRect:消息,但它没有帮助。发现内存使用问题后添加了AutoReleasePool;它也没有什么区别。

我认为这可能是因为我没有正确使用图形上下文。由于我创建的上下文的数量,在循环中调用上面的方法是个坏主意吗?或者我只是错过了什么?

- 编辑1:感谢您的评论。该方法在一个设置20个视图的控制器方法中调用,因此在循环中我有以下调用:

    UIImage *blendedImage = [newImage blendedImageOn:backgroundImage];

我添加了自动释放池以确保在主自动释放池释放它们之前释放图像,因此理论上在循环完成时应释放所有新的UIImages对象。无论自动释放池是否存在,分析结果都不会显示任何差异。

- 编辑2:是的,我在调用blendImageOn之前尝试添加自动释放池:同样,没有效果。

- 编辑3:修复因自动释放池而被释放的UIImage的尴尬错误。自动释放池的目的是释放除结果UIImage之外的任何对象,以防由于添加到主自动释放池的临时对象由于未立即释放而导致过多内存。

我试图提出的问题(非常糟糕,我承认!)是:为什么调用此方法20次会导致大量内存使用?

4 个答案:

答案 0 :(得分:1)

您不应直接调用drawRect:方法。改为使用[self setNeddsDisplay];(它不会帮助你解决这个问题);

关于你的泄漏。删除有关池的一切。 您的方法返回自动释放的UIImage对象。 请将代码粘贴到您使用返回UIImage的位置,我将能够为您提供帮助。 很可能你应该在你调用blendedImageOn:的地方建立池并每3-5次迭代排空池。

答案 1 :(得分:1)

我发现内存使用过多的问题。我的图像比我预期的要大得多,并且在调用将其绘制到图形上下文中的已发布方法之前将背景图像调整为视图大小,从而解决了内存使用问题。

我仍然感到困惑的是,为什么在图像上下文结束时不回收内存。

答案 2 :(得分:0)

您的代码的一个问题是您获得的blendedImage对象被标记为自动释放,当您释放临时自动释放池时,poof,您也会释放blendImage。

你可以保留直到游泳池被释放,然后将其恢复为自动释放:

...
UIImage* blendedImage = UIGraphicsGetImageFromCurrentImageContext(); 

UIGraphicsEndImageContext();
[blendedImage retain];       // keep this past pool release
[pool release];

[blendedimage autorelease];  // now it will be autoreleased from the main pool

return [blendedImage release];  // release to balance out the retain above

答案 3 :(得分:-1)

根据iPhone memory usage guidelines,任何返回“拥有”对象(未自动释放)的方法都应该以“alloc”或“new”开头,或者它应该包含“copy”。

您的名字“blendedImageOn”不遵循这些指南。如果您在一个月内使用它,或者其他人使用它,您将不会记得图像保留在内部并且您将有内存泄漏。