9

我有一个 UITableView,它从数据库中检索一些数据,这些数据的预取成本相对较高。为了解决这个问题,我使用了LazyTableImages示例代码中的设计理念,在滚动结束时使用[UITableView visibleCells].

这在性能方面效果很好,但它有两个我想解决的交互问题:

  1. 直到滚动完全停止(即scrollViewDidEndDecelerating)才加载数据。因此,如果我在列表中缓慢滚动,我必须停止滚动才能将数据加载到这些可见单元格中。理想情况下,如果滚动速度很慢,我会将数据加载到单元格中。
  2. 我想预取 1 或 2 个表格单元格数据,这些表格单元格数据刚刚离开屏幕,期待滚动到它们。

有没有一种优雅的方式来实现这一目标?我觉得我可能错过了解决这个问题的通用设计模式。

4

5 回答 5

6

我认为您可以在滚动开始时开始加载数据,这样您就不必等待滚动结束。您可以使用以下两种方法之一:

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView{}

而且您始终可以获取可见单元格的索引,因此我认为您应该能够加载更多数据而不仅仅是可见单元格。

于 2012-11-20T15:38:43.073 回答
2

如果您按原样使用 LazyTableImages 代码,那是正常的。加载被推迟到滚动结束。在我的测试应用程序(一个简单的类似 instagram 的流)中,我使用了一种不同的方法:基本上我将单元格子类化,从单元格本身开始下载,使用单元格作为我的下载管理器的代表,然后更新单元格的 UI下载完成时

详细地

  • 我在 cellForRowAtIndexPath 方法中开始下载(如果视图正在滚动,LazyTableImages 会延迟下载,我不这样做,因为对我来说可以在滚动时加载)调用我的单元格的“startDownload”方法。
  • 我的单元子类设置为我的下载管理器的代表,当下载完成时,单元格用真实图像更改占位符(这是在自定义的“downloadManagerDidFinishDownloadForImage:(UIImage*)image”委托方法中完成的,在细胞亚类)
  • 在我的单元子类中,我重写了 prepareForReuse 方法。在这里,如果要重复使用单元格,我可以选择停止下载。就我而言,我只是取消设置委托并继续下载,因为我有一些使用核心数据进行的图像缓存,我希望缓存继续进行。

此外,您必须注意两件事:

  • 您的下载管理器需要在后台线程中工作
  • 请务必在主线程中更新您的单元格 UI。您可以使用

dispatch_async(dispatch_get_main_queue(), ^{
    //update here your cell UI
});

在委托方法中(如果该方法由您的下载管理器调用,它肯定会在后台线程中调用,因此您必须使用调度“在主线程中“移动”)。

如果你愿意,你可以看看我的例子,但它是“原样”(它是一个测试应用程序,有很多意大利面条代码和与你的问题无关的东西;-)

http://www.lombax.it/documents/InstaXplore.zip

在我的示例中,您必须查看:

  • BrowseCell <-- 单元子类
  • BrowsePhotoViewController <-- 表格视图控制器

其他的东西都和核心数据存储和instagram有关,但基本上

  • 在 cellForRowAtIndexPath 我创建一个新单元格(或重用以前的单元格)并传递一个 InstaImage 项目(我的自定义图像)
  • InstaImage 检查是否存在缓存副本,如果不存在,则开始下载,然后提醒单元格

你有一个清晰的缓存按钮可以一次又一次地尝试:-)

于 2012-11-20T10:51:12.420 回答
1

Lazy Image 逻辑是一个很好的解决方案,我曾经在我的 tableviews 中使用,但最近我一直在为 UITableViews 实现不同的解决方案。首先是实现 NSOperation 队列,就像 Apple 在 WWWDC https://developer.apple.com/videos/wwdc/2012/?include=211#211中提供的视频中的那些

或者您可以尝试创建一个无限滚动,当您到达某个 uitableviewcell 时,您将加载一个包含更多数据的新“页面”,如果您需要有关此解决方案的帮助,请告诉我!

希望这可以帮助!

此致,

乔治。

于 2012-11-24T05:07:44.383 回答
1
// called on finger up if the user dragged. decelerate is true if it will continue moving afterwards
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;



(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (!decelerate)
    {
        //fetch data for visible rows
    }
}
于 2012-11-18T15:53:00.923 回答
1

如果我没有误解你的问题,我认为你可以使用它。您确实在显示某些单元格时加载。

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

}
于 2012-11-22T09:59:24.820 回答