UITableView与有限的滚动和延迟加载
我得到了一个UITableView
充满了未知数量的行。 每行包含(例如3个)图像,应用程序从web服务收集这些信息。
对于UITableView
我实现了无限滚动。 每当表几乎到达当前的行数的末尾,我发起一个调用web服务,以获取接下来的50行数据。 我在由UITableView
调用的scrollViewDidScroll
方法中执行此操作。
- (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在其文档中build议的相同。 该图像也添加到本地NSDictionary
,所以我可以获取它时,行滚动出来的屏幕,并返回(和行重新创build)。
由于单个视图中的图片数量可能会高达2000 – 3000,因此我还将图像caching到磁盘,并在远离X行的位置清除NSDictionary
的图像。 当用户再次向下滚动时,会发生以下情况:
- 显示新行
- 将调用延迟加载方法,该方法检查映像是存在于磁盘上还是应该下载。
- 从磁盘下载或取出图像时,会执行一个代码块,在该行中显示图像。 从互联网下载的图像也被caching到磁盘。
-
UIImage
被添加到NSDictionary
以便更快速地caching需要触及的图像。 - 由于内存问题(
NSDictionary
太多的UIImage
对象会导致内存不足错误),将从NSDictionary
中删除行中15行或远离可见行的图像。
当UITableView几乎达到最后,会发生以下情况:
- UITableView几乎到达当前加载行的末尾
- 调用webservice,加载新行(50)
- 新行添加到数组中,用于
numberOfItemsInSection
方法。 - 调用
reloadData
以确保UITableView
填充额外的新行。 - 包含图像的新行执行上述步骤以延迟加载图像。
所以,我的问题是当我从web服务添加新的logging。 当我在UITableView
上调用reloadData
,一些图像再次从磁盘加载,一些滚动的时候发生了一些混乱。
我正在寻找一个解决scheme。 我尝试使用insertItemsAtIndexPaths
与新行的数量,将它们添加到UITableView
,但这使得我的懒加载方法已经下载图像(因为不知何故所有单元格是在那个时候创build的,即使它们不可见,检查是否单元格在创build过程中是可见的,提供了意想不到的结果,图像没有加载,单元格看起来很古怪等)
所以,我基本上寻找的是一个无限的滚动UITableView的解决scheme,懒惰从networking/磁盘加载图像,并像照片应用程序一样顺利。 由于图像全部加载在不同的线程,我不明白为什么滚动不如婴儿的皮肤光滑。
我不确定我是否完全赞同你的问题,但是当遇到类似的问题时,我做了一些事情。
-
我用
-tableView:cellForRowAtIndexPath:
作为我的线索从networking加载更多的数据。 我选了一个数字(在我的情况下是10),当indexPath.row + 10 >= self.data.count
加载更多的数据。- 我需要调用
-tableView:cellForRowAtIndexPath:
无论如何。 - 我没有强制callback
-scrollViewDidScroll:
更紧密的循环。
- 我需要调用
-
我将
UIImageView
为一个类,它将asynchronous加载我称为URLImageView
图像。- 在
-tableView:cellForRowAtIndexPath:
,我为URLImageView
实例分配了一个URL。 - 该分配导致后台操作,将从磁盘加载或从networking加载。
- 该操作是可取消的,所以我没有继续工作,不再需要加载的图像。
- 在
我有一个表视图与数百(但不是数千)的图像。 我一次只有2或3个表格单元。
- 我使用了
-refreshData
:它像冠军一样工作。 - 我甚至有
URLImageView
淡入图像。 这是一个非常好的效果。
我希望有帮助。
为了避免闪烁,请尝试调用beginUpdates
上的beginUpdates
,然后insertrowAtIndexPaths:withRowAnimations:
并使用endUpdates
完成。
祝你好运。