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

时间:2015-11-28 19:13:16

标签: ios uitableview uiimageview grand-central-dispatch

我在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,但滚动到单元格的顶部会给用户带来糟糕的体验。

这就是uload在reloadData上的样子。有5张图片需要下载:UI experience after UITableView reloadData

1 个答案:

答案 0 :(得分:14)

简答

  • estimatedRowHeight
  • 提供足够的喘息空间
  • UITableViewCell返回后更改dequeueReusableCellWithIdentifier 使用缓存的单元格
  • 使用reloadRowsAtIndexPaths
  • 触发单个单元格重新加载
  • 使用Core Data管理您的缓存,让NSFetchedResultsController样板代码可以完成所有UI工作。

详情

没有意外滚动,只会更新图片:

  1. 如果正在刷新的单元格 低于地平线,UITableView滚动
  2. 如果刷新的单元格高于顶部,UITableView滚动
  3. UITableView只会在单元格处于明显状态时滚动,需要的空间超出可用空间。
  4. UITableViewAutomaticDimension努力工作

    您需要告诉Cocoa Touch该单元格陈旧,以便它会触发 new dequeueReusableCellWithIdentifier,您将返回该具有适当高度的牢房 如果没有重新加载整个表视图或其中一个部分,并假设您的索引是稳定的,请调用-tableView:reloadRows:at:with:传递刚更改的单元格的indexPath和.fade动画。

    <强>代码:

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

    使用URLSession。当图像可用时,请点击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 // Save into the cache
                        DispatchQueue.main.async(execute: { () -> Void in
                            self.tableView.beginUpdates()
                            self.tableView.reloadRows(
                                at: [indexPath],
                                with: .fade)
                            self.tableView.endUpdates()
                        })
                    }
                }
            }
        })
        downloadTask.resume()
    }
    

    进入缓存后,cellForRow只是从UI线程读入它:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "id") as! CustomCell
        cell.imageView.image = cachedImages[indexPath.row]      // Read from the cache
        return cell
    }
    

    示例:从* Wikipedia *

    中获取一组随机图像

    Xcode demo

    ►在GitHub上找到此解决方案,并在Swift Recipes上找到其他详细信息。