UITableView具有无限滚动和延迟加载

时间:2012-06-30 11:39:10

标签: iphone ios cocoa-touch

我得到了UITableView,其中包含未知数量的行。每行包含(例如3个)图像,应用程序从Web服务收集此信息。

对于UITableView我实现了无限滚动。每当表几乎达到当前行数的末尾时,我就会启动对webservice的调用,以获取接下来的50行数据。我是在scrollViewDidScroll调用的UITableView方法中执行此操作。

- (void) scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGFloat actualPosition = scrollView.contentOffset.y;

    float bottomOffset = 450;
    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
        bottomOffset = 1000;

    CGFloat contentHeight = scrollView.contentSize.height - bottomOffset;
    if (actualPosition >= contentHeight && !_loading && !_cantLoadMore)
    {
        self.loading = YES;

        _currentPage++;

        NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
        [dict setObject:[NSNumber numberWithInt:_currentPage] forKey:@"page"];
        [dict setObject:[_category objectForKey:@"ID"] forKey:@"category"];

        [self performSelectorInBackground:@selector(getWallpapersInBackground:) withObject:dict];
    }
}

UITableView行中的图像是延迟加载的。每当一行可见时,图像将被加载到一个单独的线程中,并且一旦完全下载图像就会更新行。我用于延迟加载的原则与Apple在其文档中建议的相同。图像也会添加到本地NSDictionary,因此当行滚出屏幕并重新进入时(我重新创建行),我可以获取它。

由于单个视图中的图片数量最多可达到2000 - 3000,因此我还会将图像缓存到磁盘,并在{X}远超过X行时清除NSDictionary中的图像。当用户向下和向上滚动时,会发生以下情况:

  1. 显示新行
  2. 调用延迟加载方法,检查图像是否存在于磁盘上或是否应下载。
  3. 从磁盘下载或提取图像时,它会执行一个代码块,该代码块会在行中显示图像。从互联网下载的图像也会缓存到磁盘上。
  4. UIImage已添加到NSDictionary,以便更快地缓存需要触及的图片。
  5. 由于内存问题(NSDictionary中有太多UIImage个对象导致 - NSDictionary,因此会从numberOfItemsInSection中移除行中,距离可见行15行或更远的图像。内存错误。)。
  6. 当UITableView几乎到达终点时,会发生以下情况:

    1. UITableView几乎到达当前加载的行的末尾
    2. 使用大量新行(50)
    3. 调用webservice
    4. 新行将添加到数组中,该数组用于reloadData方法。
    5. 调用UITableView以确保reloadData填充额外的新行。
    6. 包含图片的新行,执行上述步骤以延迟加载图片。
    7. 所以,我遇到的问题是当我从webservice添加新记录时。当我在UITableView上调用insertItemsAtIndexPaths时,某些图像会再次从磁盘加载,并且在滚动时会出现一些hickup。

      我正在为此寻找解决方案。我尝试将UITableView与新行的数量一起使用,将它们添加到{{1}},但这使得我的延迟加载方法已经下载了图像(因为不知何时所有单元格都是在那时创建的,甚至当它们不可见时,检查在创建过程中单元格是否可见会产生意外结果,图像无法加载,单元格看起来很奇怪等等。

      所以,我基本上正在寻找的是无限滚动UITableView的解决方案,它延迟加载来自网络/磁盘的图像,并且与照片应用程序一样流畅。由于图像都是在不同的线程中加载的,我不明白为什么滚动不像婴儿的皮肤那么光滑。

2 个答案:

答案 0 :(得分:15)

我不确定我是否完全了解你的问题,但是在遇到类似的问题时我会做一些事情。

  • 我使用-tableView:cellForRowAtIndexPath:作为我的提示来从网上加载更多数据。当indexPath.row + 10 >= self.data.count加载更多数据时,我选择了一个数字(在我的情况下为10)。

    • 无论如何我需要致电-tableView:cellForRowAtIndexPath:
    • 我没有强制回调-scrollViewDidScroll:
    • 的更紧密的循环
  • 我将UIImageView子类化为一个可以异步加载图像的类,我称之为URLImageView

    • -tableView:cellForRowAtIndexPath:中,我为URLImageView实例分配了一个网址。
    • 该分配导致后台操作从磁盘加载或从Web加载。
    • 该操作已取消,因此我没有继续处理不再需要加载的图像。

我有一张包含数百张(但不是数千张)图像的桌面视图。我一次只在屏幕上有2或3个表格单元格。

  • 我使用-refreshData:它就像一个冠军。
  • 我甚至让URLImageView淡出图像。这是一个非常好的效果。

我希望有所帮助。

答案 1 :(得分:2)

为避免闪烁,请尝试在桌面上调用beginUpdates,然后insertrowAtIndexPaths:withRowAnimations:并以endUpdates结束。

祝你好运。