11

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

对于UITableView我实现了无限滚动。每当表几乎达到当前行数的末尾时,我都会调用 Web 服务,以获取接下来的 50 行数据。我scrollViewDidScrollUITableView.

- (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 在其文档中建议的相同。图像也被添加到 local NSDictionary,因此当行滚动出屏幕并返回(并重新创建行)时,我可以获取它。

因为单个视图中的图片数量可以达到 2000 - 3000,所以我还将图像缓存到磁盘,并在距离NSDictionary超过 X 行时清除图像。当用户再次向下和向上滚动时,会发生以下情况:

  1. 显示新行
  2. 调用延迟加载方法,它检查图像是否存在于磁盘上或者是否应该下载它。
  3. 当从磁盘下载或获取图像时,它会执行一个代码块,将图像显示在行中。从 Internet 下载的图像也会缓存到磁盘。
  4. UIImage添加到NSDictionary以更快地缓存需要触手可及的图像。
  5. 由于内存问题(导致内存不足错误的对象NSDictionary过多),从可见行中删除的行中、15 行或更远的图像将从 中删除。UIImageNSDictionary

当 UITableView 快走到尽头时,会出现以下情况:

  1. UITableView 几乎到达当前加载行的末尾
  2. 调用 web 服务,加载新行 (50)
  3. 新行被添加到用于该numberOfItemsInSection方法的数组中。
  4. 调用AreloadData以确保UITableView填充额外的新行。
  5. 包含图像的新行执行上述步骤以延迟加载图像。

所以,我遇到的问题是当我从 web 服务添加新记录时。当我调用 areloadData时,UITableView一些图像再次从磁盘加载,并且在滚动时发生了一些小问题。

我正在为此寻找解决方案。我尝试使用insertItemsAtIndexPaths新行的数量,将它们添加到 中UITableView,但这使得我的延迟加载方法已经下载了图像(因为当时以某种方式创建了所有单元格,即使它们不可见,检查单元格是否在创建过程中可见会产生意想不到的结果、图像未加载、单元格看起来很奇怪等)。

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

4

2 回答 2

16

我不确定我是否完全理解你的问题,但这里有一些我在遇到类似问题时所做的事情。

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

    • -tableView:cellForRowAtIndexPath:反正我需要打电话。
    • 我没有强制回调到更紧密的-scrollViewDidScroll:.
  • UIImageView使用一个可以异步加载我调用的图像的类进行子类化URLImageView

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

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

  • 我用过-refreshData:它像冠军一样工作。
  • 我什URLImageView至不得不淡出图像。这是一个非常好的效果。

我希望这会有所帮助。

于 2012-06-30T23:58:56.203 回答
2

为避免闪烁,请尝试beginUpdates在桌子上呼叫,然后以 .insertrowAtIndexPaths:withRowAnimations:结束endUpdates

祝你好运。

于 2015-04-05T11:36:48.687 回答