图像下载后更新单元格高度

我在UITableView显示一些文本和图像。 图片首先被下载。 由于在下载图像之前,我不知道图像的大小,所以我最初把一些固定大小的UIImageView 。 当图像下载时,我调整了UIImageView大小。

 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // Download image dispatch_async(dispatch_get_main_queue(), ^{ // UIImageView resizing }); }); 

所有这一切发生在cellForRowAtIndexPath
我在这里面临的问题是:
1.如何更新单元格的高度? 考虑到在一个单元中可以有许多图像。 所以我需要在一次下载时改变底部图像的位置。
2.我尝试使用UITableView beginUpdatesendUpdates ,但是滚动到单元格的顶部,给用户带来不好的体验。

这是UI在reloadData上的样子。 有5个图像被下载: UITableView reloadData后的UI体验

简答

  • 给予estimatedRowHeight高度足够的呼吸空间
  • 一旦由dequeueReusableCellWithIdentifier返回,更改UITableViewCell无法使用caching的单元格
  • 使用reloadRowsAtIndexPaths触发单个单元重新加载
  • 使用核心数据pipe理你的caching,让NSFetchedResultsController样板代码可以做所有的UI工作。

在细节

下面的代码不会滚动:

  1. 如果正在刷新的单元格位于或低于地平线, UITableView将不会滚动
  2. 如果正在刷新的单元格在顶部之上, UITableView将不会滚动
  3. UITableView只会在单元格显示时才会滚动,并且需要比可用空间更多的空间。

UITableViewAutomaticDimension努力工作

你需要告诉Cocoa Touch单元格是陈旧的 ,所以它会触发一个新的 dequeueReusableCellWithIdentifier ,你将返回一个适当高度的单元格
在重载整个表视图或其中一个部分之后,假设索引是稳定的,调用-tableView:reloadRows:at:with:传递刚刚更改的单元格的.fade.fadeanimation。

码:

 override func viewDidLoad() { super.viewDidLoad() tableView.estimatedRowHeight = 250 // match your tallest cell tableView.rowHeight = UITableViewAutomaticDimension } 

使用URLSession 。 当图像变得可用时,fire reloadRows:at:with

 func loadImage(_ url: URL, indexPath: IndexPath) { let downloadTask:URLSessionDownloadTask = URLSession.shared.downloadTask(with: url, completionHandler: { (location: URL?, response: URLResponse?, error: Error?) -> Void in if let location = location { if let data:Data = try? Data(contentsOf: location) { if let image:UIImage = UIImage(data: data) { self.cachedImages![indexPath.row] = image self.cachedUrls![indexPath.row] = url DispatchQueue.main.async(execute: { () -> Void in self.tableView.beginUpdates() self.tableView.reloadRows( at: [indexPath], with: .fade) self.tableView.endUpdates() }) } } } }) downloadTask.resume() } 

示例:从*维基百科获取一组随机图像*

Xcode演示

►在GitHub上find这个解决scheme和Swift Recipes的更多细节。