2

我有一个 UIImage,我正在使用 imageWithData 实例化:(数据是使用 [NSData dataWithContentsOfFile:] 从包中加载的)。

然后我像这样绘制图像:

NSData *imageData =  [NSData dataWithContentsOfFile:fileLocation];
UIImage *myImage = [UIImage imageWithData:imageData];

//These lines are superfluous from what I can tell, replacing with
//UIImage *myImage = [UIImage imagedNamed:imageName]; very soon.

[myImage drawAtPoint:CGPointMake(0,0)];
//myImage will be released at the end of the run loop

我的问题是:创建的 UIImage 是自动发布的。当 UIImage 被绘制到视图然后 UIImage 被解除分配不存在时,在内存方面会发生什么。显然,在视觉上,图像仍然存在,因为它已被绘制到上下文中。

如果 UIImage 有效并且已被绘制到视图,内存使用量是否会翻倍,然后在 UIImage 被释放后返回到与仅存在一个 UIImage 相同的数量?


现在走另一条路。

如果我使用 [UIImage imageNamed:] 来实例化图像,那么 UIImage 类具有自己的各种图像缓存,并且只会保存特定图像的一个真实实例(无论创建了多少 UIImage 实例来表示该图像)。

我的另一个问题是:如果我将缓存中的图像绘制到上下文然后释放 UIimage(通过运行循环结束时的自动释放),会发生什么情况?图像是否留在缓存中消耗内存?是否因为没有其他 UIImage 实例正在使用它而被删除?

任何帮助都会很棒,谢谢!

4

3 回答 3

1

在任何时候,当您“绘制到上下文”时,上下文不包含对图像的引用。相反,绘图会将像素的实际位放置在上下文中,因此它不需要对 UIImage 的引用(或任何绘制到它的东西 - NSString、NSPath 等)。

关于imageNamed:,它永远不会真正发布 - 您得到的是您不(也不应该)发布的参考,但缓存的图像可能仍然存在。

于 2009-08-18T13:40:29.917 回答
1

我真的建议从这里的简单代码开始,然后优化你实际遇到问题的地方。您描述的那种空间优化可能会产生严重的时间问题(-drawRect:例如,重新创建 UIImage 非常昂贵)。也就是说,让我们看一下各种问题:

  • 首先,正如我所说,小心在-drawRect:. 您几乎无法控制调用它的频率或时间,并且这里的任何昂贵工作(例如创建新的 UIImage,特别是如果您必须从磁盘读取它时)都会严重影响 UI 性能。

  • 我假设您的内容还有很多,对-drawRect:吗?UIImageView针对您在此处所做的工作进行了优化,包括速度和内存。但是,如果您的视图要复杂得多,那么自己绘制图像比创建大量子视图要好。

  • 如前所述,当您调用 时-drawAtPoint:,您制作的副本是位图表示(与完成的任何其他绘图混合)。就内存使用而言,它与原始 UIImage 无关。你不能用一个换另一个。位图表示所需的内存是视图大小和位深度的函数,您无法更改它。它不关心 UIImage 在绘制后是否存在。

  • -imageNamed:确实为您做缓存,通常是一个不错的选择。请注意,它不会在内存不足的情况下清除其缓存。如果 UIImages 是从文件中加载的,则它们本身会透明地转储其基础数据(并且在任何情况下它们都会转储额外的表示)。UIImage 参考包含有关如何完成此操作的信息。

  • 如果您非常关心这些图像(空间或时间)的性能,并且不需要 UIImage 的功能,那么您应该使用 CGImages。它们不像 UIImage 那样灵活,而且它们的代码更复杂,但它们更高效。也就是说,UIImages 适用于大多数用途。

于 2009-08-18T14:33:01.087 回答
0

这实际上取决于您在哪里创建 UIImage 实例本身。如果这是 UIView 子类,您是在其他地方或其他地方创建 UIImage-drawRect:-initWithFrame:?如果您加载一次图像(在您的 init 中或使用保留的 setter 等),那么应该没有问题。但是,如果您一遍又一遍地创建图像,-drawRect:那么至少您将遇到性能问题。

于 2009-08-18T13:45:31.457 回答