5

一周前,Apple 刚刚在 UITableView 中发布了一些关于延迟加载图像的示例代码。我检查了它并将其实现到我自己的 UITableView (这是一个用于快速滚动的 drawRect ),看看是否与我已经在做的不同。

实施后我不确定什么是最好的;新代码或我已经拥有的代码。我没有看到我的 3GS 的速度有很大提高。

“沙盒”方法:懒加载图片,然后保存到沙盒中的本地tmp文件夹。每次显示单元格时,它都会查找具有该文件名的图像是否已位于沙箱文件夹中。如果是,它会检索图像并显示它,如果不是,它会继续下载,将其保存在本地,然后显示它。这样做的好处是第二次打开应用程序时图像不会是空白的。它们已经被下载并准备好显示。

缓存方法:这也会延迟加载图像,但是,现在我在 tableview 中显示的数组中的每个对象上都包含一个 UIImage。我现在不是在本地保存图像,而是下载图像并将其放入对象的数组中。现在,它不是每次都检查文件名,而是检查 UIImage 是否!= nil 并使用缓存的图像(如果为 nil,则下载)。

一个小的区别还在于,缓存代码在将图像缓存到单元格中显示的确切大小之前会调整其大小,而沙盒代码示例中使用的图像实际上比它需要显示的要大一些,这意味着它也必须在滚动时动态调整大小。几个月前我读到这可能有点贵,而且我也不确定它是否会在使用缓存图像而不是沙盒存储图像方面产生很大差异,因此无论如何都会占用更多 CPU(相比之下到您使用上面的缓存代码从缓存中保存的内容)。

我想我的问题是我是否应该打扰缓存代码?同样,新代码不会在新启动时立即加载图像,而旧代码实际上会这样做,因为它已经在沙箱中。由于我没有重用图像,我有很多图像要加载(从沙箱或缓存中),所以我没有注意到速度上有很大的差异。事实上,在我看来,在我的 3GS 上几乎无法分辨。滚动不是如丝般顺滑,我认为这是由于我无法重复使用大量图像(每个单元格的图像不同)。我还想知道,例如,一旦文件夹中有 1000 多张图像,沙盒方法是否会变慢,例如,最终让它查看更多的图像,而不仅仅是 100 幅左右。

我希望我说得通。我想对细节非常透彻,如果需要,我很乐意提供更多细节。

谢谢!

4

3 回答 3

1

如果您的代码已经可以运行,并且没有紧迫的问题,那么不要更改它。

如果您的滚动实际上太慢,那么也许您可以混合使用想法,并尝试获取 UIImage,如果它不存在,则从沙箱中加载它,如果它不存在,则下载它。

于 2009-11-23T15:41:59.893 回答
0

判断性能是否存在明显差异的唯一好方法是使用分析工具,如 Instruments(用于测量两种技术的显示帧速率等)或 Shark(确定代码中的热点)。您的确切实现可能存在微小差异,这可能会导致我们可以给出的任何一般答案与您在应用程序中看到的实际性能之间存在显着差异。

与“沙盒”方法有关的主要问题不是性能,而是磁盘空间使用情况。用户不会喜欢你用不必要的文件填满他们的 iPhone 或 iPod Touch,特别是如果所有图像都没有一致使用或者使用的图像集经常更改。如果不了解您的应用程序的更多信息,就无法猜测这些缓存图像的加载频率。

如果您在自己的设备上进行本地测试,您可能在 Wifi 网络上。我的建议是在您的部分测试中关闭 Wifi,以查看当您必须通过蜂窝网络获取所有图像时这两种方法的执行情况。我还建议尝试寻找旧设备(iPhone 3G 或更差),因为 3GS 实际上隐藏了可能对旧设备用户造成困扰的潜在性能问题。

我个人在我的应用程序中多次使用 LazyTableImages 技术(前提是它在 WWDC09 和最近的“发布”之间没有发生太大变化)并且发现它正是我所需要的。但是,在我的情况下,将图像缓存在磁盘上不是一种选择,并且您不应该过于强烈地考虑我的轶事 - 分析您自己的代码并使用它显示的结果。

编辑:

显而易见的答案是访问内存中的缓存将比访问文件系统更快,但当然最后的决定权留给分析。如果图像已经在内存中,则不需要从闪存中读取它们并由 UIImage 解析。然而,传统的权衡在这里发挥作用 - 内存缓存与磁盘空间。

虽然将图像存储在内存中可能会更快,但您需要非常确定您正确处理应用程序中的内存警告(无论如何您都应该这样做!)。否则长时间使用会导致内存缓存中有很多图像并触发内存警告,如果您的应用程序不是为处理这些问题而构建的,那么您的应用程序最多会因内存资源不足而被操作系统杀死。

于 2009-11-23T15:22:45.253 回答
0

您提出的两种方法各有利弊 - 我建议在您的应用程序中使用这两种方法的元素。

最好将图像保存在内存中并稍后保存(可能在您的应用退出时)。如果你有很多图像,使用 Core Data 保存它们可能比保存常规文件更快。

最好避免即时调整大小,即在您的 tableView:cellForRowAtIndexPath: 或 tableView:willDisplayCell:forRowAtIndexPath: 方法或与绘制单元格内容视图有关的任何方法中。如果可以,请要求图像提供者(内容管理?)以表格视图显示的大小提供图像。

于 2009-11-26T09:06:10.220 回答