[UIImage imageNamed ...]和[UIImage imageWithData ...]之间的区别?

时间:2008-11-25 02:53:28

标签: iphone cocoa-touch

我想从文件系统将一些图像加载到我的应用程序中。有两种简单的方法可以做到这一点:

[UIImage imageNamed:fullFileName]

或:

NSString *fileLocation = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
NSData *imageData = [NSData dataWithContentsOfFile:fileLocation];

[UIImage imageWithData:imageData];

我更喜欢第一个,因为它的代码少得多,但是我看到有些人说图像被缓存了,而且这个方法使用了更多的内存?由于我不相信大多数其他论坛上的人,我想我会问这里的问题,是否有任何实际的区别,如果是的话哪一个更“好”?

我尝试使用对象分配工具分析我的应用程序,虽然我只是在模拟器中尝试过而不是在iPhone本身上,但我看不出任何实际差异。

8 个答案:

答案 0 :(得分:91)

这取决于您对图像的处理方式。 imageNamed:方法会对图像进行缓存,但在许多情况下,这会有助于内存使用。例如,如果将图像加载10次以与表视图中的某些文本一起显示,则UIImage将仅在内存中保留该图像的单个表示,而不是分配10个单独的对象。另一方面,如果你有一个非常大的图像并且你没有重新使用它,你可能想要从数据对象加载图像,以确保它在你完成后从内存中删除。

如果你没有任何巨大的图像,我不会担心。除非你看到一个问题(并且赞成检查对象分配而不是抢先优化),否则我会选择较少的代码行而不是可忽略的内存改进。

答案 1 :(得分:10)

根据我的经验[UIImage imageNamed:]表现得更好,尤其是在UITableViews中使用时。

它不仅仅是内存,还能解码image。缓存它会更快。

答案 2 :(得分:10)

由于 UIImage 的API参考说明:

  

+(UIImage *)imageNamed:(NSString *)name

     

此方法在系统缓存中查找具有指定名称的图像对象,并返回该对象(如果存在)。如果匹配的图像对象尚未在缓存中,则此方法从指定的文件加载图像数据,对其进行缓存,然后返回结果对象。

     

+(UIImage *)imageWithContentsOfFile:(NSString *)路径

     

此方法不会缓存图像对象。

所以,我们可以看到,如果您有很多相同的 UI元素(例如UITableViewCell)可能使用相同的图像(通常作为图标),并且由于性能的原因,我们当然希望重用相同的图像,这样我们就可以节省一些内存用于其他用途。通常,重用图像通常用于我们的用户可能对其进行操作的ui元素很多次。所以它重视我们重用它。所以你可以选择使用 imageNamed 方法。

另一方面,在应用程序中,应用程序的生命周期中会有一些 UI元素,例如Button,徽标视图,所以这些图像由在应用程序的生命周期中,这些ui元素也可能存在,您不会考虑这些图像是否应该缓存。因此,您可以选择使用 imageNamed 方法。


相反,在应用程序中,通常会动态创建一些 UI元素。例如,我们的应用程序支持动态背景,以便用户可以选择他们喜欢的背景。背景可能是一个图像。所以我们可能有一个列出批次的界面使用背景(通常使用 UIImageView 显示)供用户选择,我们可以将列表视图命名为 MyBackgroundListView 。一旦用户选择了背景图像 MyBackgroundListView 应该被销毁,因为它已经完成了它的功能。下次用户想要改变他/她的背景时,我们可以创建 MyBackgroundListView 再次。 MyBackgroundListView 使用的图片不应该被缓存,或者我们的应用程序的内存将耗尽。所以这次你应该使用 imageWithContentsOfFile 方法。

正如Apple的文档Supporting High-Resolution Screens In Views所说

  

在具有高分辨率屏幕的设备上, imageNamed: imageWithContentsOfFile: initWithContentsOfFile:方法会自动查找某个版本的请求图像名称中包含@ 2x修饰符。如果找到一个,则会加载该图像。如果您未提供给定图像的高分辨率版本,则图像对象仍会加载标准分辨率图像(如果存在)并在绘图期间对其进行缩放。

所以你会担心图像的视网膜屏幕问题的搜索路径。 IOS将帮助您处理它。

抱歉我的英语不好。愿它有用。

答案 3 :(得分:7)

如果您不希望缓存图像,也可以直接使用initWithContentsOfFile:

NSString *fileLocation = [[NSBundle mainBundle] pathForResource:fileName ofType:extension];
UIImage* yourImage = [[[UIImage alloc] initWithContentsOfFile:imagePath] autorelease];

答案 4 :(得分:5)

我也被告知[UIImage imageNamed:]缓存太多,图像不经常发布。有人告诉我要小心使用它。

答案 5 :(得分:3)

当您将图像二进制文件存储在数据库中或逐步从Web下载大图像时,

imageWithData非常有用。

答案 6 :(得分:0)

如果你的应用程序有大量不同的大图像,我不会使用imagenamed。由于使用了太多,我经历了应用程序崩溃。

答案 7 :(得分:-11)

我不相信图像会被缓存,我不知道你为什么这么说。 UIImage是NSObject的子类,它使用引用计数器来跟踪与之相关的事物。因此,当您加载图像时,它会执行相同的操作。如果您多次加载相同的图像,它将(或应该)在内存中只有一个图像副本,并且每次必须使用该图像时,只需递增参考计数器。通过引用计数器我的意思是当计数达到0时它会自行删除。所以“alloc”,“retain”每个都是+1,而“release”是-1。它不仅是管理内存的更好方法,而且这种编程风格也有助于清理内存泄漏。