将数据异步加载到表格视图单元格中的正确方法/接受标准是什么?

许多应用程序,如Tweetbot , Twitterrific , Alien Blue等,显示来自API的图像似乎以异步方式加载它们。 似乎初始可视图像是同步加载的 – 即初始可视单元格在它们的图像准备好之前不会显示 – 但是当进一步向下滚动到初始可视单元格之后,似乎这些新单元格的图像是独立于初始同步负载。

例如,当用户在Twitter应用程序中加载推文时,直到用户头像的图像加载后才会显示最初的六条或七条推文,但是之后的40多条推文(不是’在用户滚动之前可见,我们不必等待这些图像加载以显示初始单元格,因为它们甚至还不可见。 似乎大多数应用程序允许这些图像独立加载,使初始推文更快地显示出来。

我很困惑如何最好地实现这一点,例如,如果大多数开发人员都采用标准方式来做这件事我不知道。

我习惯于通过从响应向Core Data提供对象来使用Core Data,然后NSFetchedResultsController在表视图中显示它们。 然而,这会产生负面影响,要求在显示单元格之前将所有内容完全加载并存储在对象中。 这意味着如果API返回一个图像链接给我,我想在单元格中显示该图像,我必须将链接加载到UIImage并将其添加到Core Data。

所以我的问题基本归结为: Tweetbot,Twitterrific,Alien Blue等热门应用程序如何处理需要加载大量图像和数据的表格视图,但仍允许非常快速的加载,而不必加载不必要的数据,仍然保持高滚动性能?

有很多解决方案,你可以在这里找到很多关于堆栈溢出的解决方案。

基本思路是你想要在块或NSOperation加载图像。 我更喜欢NSOperation因为你可以取消它们,这在单元格NSOperation屏幕时很有用。

我建议使用控制器来管理您的图像队列。 您的表格单元格从控制器请求图像,如果控制器具有图像,则立即返回该图像。 如果没有则返回nil并获取图像。

从这里可以选择。 您可以使用块在检索图像时回调。 我不喜欢它,但它很受欢迎。 我更喜欢在收到图像时使用NSNotification ,并且单元格侦听要填充的NSNotification

我在github上有一个相当复杂的样本,可以处理这个以及更多。 它位于我的共享存储库中, url为http://github.com/ZarraStudios/ZDS_Shared 。 主类称为ZSAssetManager

注意:此示例代码已有几年的历史,因此它不支持ARC ,需要进行一些调整。 它也可能比您正在寻找的更复杂,因为它也处理带宽检测和反应。 但是,它向您展示了生产/高质量应用程序处理异步加载图像的function。

请享用。

Apple文档中有一些示例代码,演示了如何将图像延迟加载到表格视图单元格中。 它负责取消滚动视线之外的图像的下载,并且在用户停止滚动之前根本不开始图像下载。

没有完美的答案。 这是一种艺术forms,可以改进和调整所涉及的各种部分,为您的应用提供最佳用户体验。 尽管如此,你所描述的内容包括以下方面的精通组合:

延迟加载

对于延迟加载,我最喜欢的goto是SDWebImage 。 为了达到效果,您可以描述前6或7条推文在图像存在之前不加载的位置,您可以先隐藏推文并使用SDWebImage的完成块取消隐藏它们。

分页

分页是指最初检索一定数量的对象并在用户到达之前异步拉下下X个对象(通常由滚动启动)的做法。 您还可以将此扩展为仅在用户的滚动减慢或停止时加载图像,因此您不会浪费时间加载用户滚动过去的图像。 在GitHub上有一些很好的例子,比如NMPaginator ,或者你可以使用UIScrollViewDelegate方法自己动手。

设置您的scrollview委托并实现:

 - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (!decelerate) { [self loadImagesForVisibleRows]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { [self loadImagesForVisibleRows]; } 

然后添加一个loadImagesForVisibleRows方法,在其中使用[self.tableView indexPathsForVisibleRows]; 访问可见行并延迟加载这些行的图像。

有效的有效载荷

最后,如果您保持有效负载清洁和轻便,它将为您节省一些加载时间,尤其是对于网络连接较弱的用户。 我推荐了Vinay的Sahni的博客文章, 设计一个实用的RESTful API的最佳实践 ,以获取有关RESTful API设计和分页的大量信息。

欢迎对上述内容的任何建议或补充。

我一直在使用dispatch_async将数据异步加载到我的表视图单元格中:

 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); dispatch_async(queue, ^{ NSData *imageData = [NSData dataWithContentsOfURL:url]; dispatch_async(dispatch_get_main_queue(), ^{ UIImage *image = [UIImage imageWithData:imageData]; [imageView setImage:image]; }); }); 

我在这个例子中使用的图像只有几千字节(每个),并且它们非常好地加载到表格视图中。