iOS TableView使用Swift预取数据源

Apple引入了用于在iOS 10中预取UITableViewUICollectionView的 API。这是有关如何实现UITableViewDataSourcePrefetching协议的简短故事。

总览

为了实现预取,我们向视图控制器确认了UITableViewDataSourcePrefetching协议,就像UITableViewDataSourceUITableViewDelegate一样 。 这使表视图的数据源可以在调用tableView(_:cellForRowAt 🙂数据源方法之前开始为单元格加载数据。

入门

将视图控制器设置为表视图预取数据源

  tableView.prefetchDataSource =自我 

tableView(_:prefetchRowsAt :)的实现中,初始化指定索引路径中单元格所需的数据的异步加载。

  func tableView(_ tableView:UITableView,prefetchRowsAt indexPaths:[IndexPath]){ 
用于indexPaths中的indexPath {
警卫让_ = loadingOperations [indexPath]否则{返回}
如果让dataLoader = dataStore.loadPhoto(at:indexPath.row){
loadingQueue.addOperation(dataLoader)
loadingOperations [indexPath] = dataLoader
}
}
}

当表视图通知您tableView(_:cancelPrefetchingForRowsAt 🙂方法不再需要数据时,取消挂起的数据加载操作

  func tableView(_ tableView:UITableView,cancelPrefetchingForRowsAt indexPaths:[IndexPath]){ 
用于indexPaths中的indexPath {
如果让dataLoader = loadingOperations [indexPath] {
dataLoader.cancel()
loadingOperations.removeValue(forKey:indexPath)
}
}
}

异步加载数据

tableView(_:cellForRowAt :)不同tableView(_:prefetchRowsAt 🙂方法不一定在表视图中的每个单元格中都被调用。 对于屏幕上不可见的单元格,将调用它。 因此, tableView(_:cellForRowAt :)的实现必须能够处理以下潜在情况

  • 数据已通过预取请求加载并准备显示。
  ... 
//是否已加载数据?
如果让image = dataLoader.image {
cell.updateAppearanceFor(image)
loadingOperations.removeValue(forKey:indexPath)
}
...
  • 当前正在预取数据,但尚不可用。
  ... 
其他{
//尚未加载任何数据,因此添加完成闭包以在数据到达后更新单元格
dataLoader.loadingCompleteHandler = updateCellClosure
}
...
  • 尚未请求数据。
  //需要创建为此索引路径加载的数据 
如果让dataLoader = dataStore.loadImage(at:indexPath.row){
//提供完成闭包,并开始加载操作
dataLoader.loadingCompleteHandler = updateCellClosure
loadingQueue.addOperation(dataLoader)
loadingOperations [indexPath] = dataLoader
}

为了处理所有这些情况,操作用于加载每一行的数据。 我们创建Operation对象并将其存储在prefetch方法中。 然后,数据源方法可以检索操作和结果,或者如果不存在则创建新操作。

 类DataLoadOperation:操作{ 
var image:UIImage?
var loadingCompleteHandler:(((UIImage?)->())?
私人var _image:ImageModel

init(_ image:ImageModel){
_image =图片
}

覆盖func main(){
如果isCancelled {返回}
守护让url = _image.url else {return}
downloadImageFrom(url){(image)在
DispatchQueue.main.async(){[弱自我]在
守卫let`self` = self else {return}
如果self.isCancelled {返回}
self.image =图片
self.loadingCompleteHandler?(self.image)
}
}
}
}

结论

我希望您喜欢本教程,并希望它可以帮助您了解如何实现预取协议,并使您的应用与用户更加互动。 试图非常简短和集中。 如果您想了解有关Apple预取协议的更多信息,我鼓励您观看有关预取协议的Apple WWDC会议。

只有源代码是真实的:

rokonuddin / TableViewPrefetch

UITableViewDataSourcePrefetching协议的实现– rokonuddin / TableViewPrefetch

github.com

谢谢大家的关注🙏🏻。 随时发推文并建立联系。