缓存UIImages在UITableView中获取性能

时间:2010-08-10 18:42:49

标签: iphone performance uitableview core-data

我一直在使用@ atebits的ABTableViewCell一段时间。对于那些不熟悉它的人来说,基本上它通过绘制所有标签和图像使tableview滚动更多更快,而不是分配UIKit对象(如UILabels,UIImageView等)。

现在,我有一个非常大的UITableViews,在每个单元格中,有一个小的(32x32)用户图像和一个中等(75x75)的照片缩略图。该绘图确实有助于使这个tableview快速滚动,但我仍然试图找出获取这些将在单元格内绘制的图像的最佳方法。

我看过Apple的LazyTableView示例,但我仍然不确定最好的方法是什么。我所知道的是cellForRowAtIndexPath:中的代码/分配越少,就越好。

所以我的图像要么从服务器下载,要么从我的CoreDataHelper中检索。我的问题是:以下哪种方法更适合检索缓存的图像

  1. NSFetchRequest中使用cellForRowAtIndexPath:来获取缓存的图像(因此在表视图滚动时分配NSFetchRequest实例)。

  2. 从tableView的数据源开始保留所有缓存的图像,这样我就可以从我viewDidLoad:中的UITableViewController}数据源中的已经分配的数组中获取它们。这种方法显然占用了更多的内存,因为它分配了一堆小图像,但我猜测滚动会更顺畅。

  3. 任何人都可以为此加油吗?

    (顺便说一句,我希望图像在桌面视图滚动时显示 。等待它停止滚动以加载图像不是一种选择。)


    编辑:从磁盘加载图片

    按照提供的答案,我现在正尝试使用图像本地路径直接从磁盘加载图像(显然是在保存之后),这是tableview数据源的一部分。这是cellForRowAtIndexPath:方法中的代码:

    NSData *imageData = [NSData dataWithContentsOfFile:imageLocalPath];     
    UIImage *userImage = [UIImage imageWithData:imageData];
    cell.avatarImage = userImage;
    

    它仍然不是黄油平滑(每次出现一个新单元格时会出现一个小的延迟(每次cellForRowAtIndexPath:被调用)我应该异步进行此调用吗?或者磁盘读取速度足够快且绝对不是问题这里吗?


    编辑:更多详情

    1。你在哪里得到imageLocalPath?

    图片网址是我的dataSource的一部分,这是一个在viewDidLoad中分配的NSArray(缓存到CoreData但不应影响滚动)。 app文档目录路径也保留在viewDidLoad中,因此使用

    在cellForRowAtIndexPath中计算整个文件路径
    NSArray *urlArray = [picURLString componentsSeparatedByString: @"/"];
    NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsPath, [urlArray lastObject];
    

    2。当你通过鲨鱼运行时会发生什么?

    我之前从未使用过Shark,试图使用它,显然iOS 4不再支持它。你能证实这一点吗?当我点击“开始”按钮时,没有任何反应。

    第3。您在设备上使用仪器的FPS是什么?

    我的速度在25到30fps之间,但在实际屏幕上看起来并不是那么顺畅。不确定这是否意味着什么。我觉得我得到了10-15fps。再一次,在单元格之间滚动是平滑的,就在桌面视图遇到一个新的单元格时,有一个轻微的延迟(如此快速的滚动=每秒的许多小滞后)。

3 个答案:

答案 0 :(得分:2)

您确定图片是您的问题吗?你在桌子上做过阿尔法检查了吗?根据我的经验,加载图像几乎不是表格滚动的表现,它几乎总是alpha通道问题。

在走这条路之前,我会先在仪器上打开alpha测试。

更新

我想知道你首先加载数据是否是一个障碍:

UIImage *userImage = [UIImage imageWithContentsOfFile:imageLocalPath];
[cell setAvatarImage:userImage];

应该UIImage为您做一些缓存工作。

  • 你在哪里获得imageLocalPath?
  • 是存储在核心数据实体中还是正在进行计算?
  • 当你通过鲨鱼跑步时会发生什么?
  • 你在设备上使用仪器的FPS是什么?

更新2

为什么要使用Core Data对象并将它们存储到NSArray?在大多数情况下,您应该使用NSFetchedResultsController

你不应该构建filePath,这需要时间并且-componentsSeparatedByString:正在进行字符串搜索;非常慢。保存图像时存储文件路径。快多了。如果您不想更改模型,请将其设为在-awakeFromFetch:上解决的瞬态值。

自iOS4起,Shark的功能与Instruments集成。

25-30 FPS并不理想,但相当不错。这意味着你获得了良好的帧速率和微小的调整(对于主要的基本问题)可能会让它更高。

答案 1 :(得分:0)

保留所有图像以供参考不具备可扩展性。用这种方式杀死旧款iPod并不需要太多。

根据我的经验,CoreData只是缓慢的。将CoreData对象在滚动表中导入表视图不是一个好主意。

我的解释是你在CoreData中存储二进制图像?那可能是你的问题。您可能需要在此处信任磁盘I / O.我是一个应用程序的主管,它有一个带有两倍大的缩略图的tableview,我通过将数据写入磁盘上的文件并检索它来手动完成所有缓存...如果它不在缓存中我使用ASIHTTPRequest来拉。

iPhone上的黄油很平滑,即使必须上网查看一些图像。只要您以异步方式读取缓存,就可以了。

答案 2 :(得分:-2)

我不太熟悉使用CoreData但我确实认为CoreData是某种缓存,所以你自己缓存它或者你使用NSFetchRequest,它最终会在内存中进行快速访问。另外,我真的不喜欢CoreData,因为它本身就是一个数据库,必须与服务器保持同步,最终效率低下(这是我自己的经验)

我个人会沿着#2的路线前进。因为您可以使用ASIHTTPRequest框架之类的东西来执行支持缓存和其他多个选项(如队列)的所有传输操作。

另一方面,滚动停止后出现的图像问题仅仅是由于在主运行循环外发生的UIScrollView滚动操作,您可以通过在当前运行循环上调用绘图操作来轻松解决此问题滚动时会出现(如果你在每个细胞上做一些沉重的东西,这显然会影响表现)