图像下载后更新单元格高度 [英] Updating cell height after image downloads

查看:106
本文介绍了图像下载后更新单元格高度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 UITableView 中显示一些文字和图片。首先下载图像。从图像下载之前,我不知道图像的大小,所以我最初放了一些固定大小的 UIImageView 。下载图像后,我调整 UIImageView 的大小。

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^ {

//下载图片

dispatch_async(dispatch_get_main_queue(),^ {

// UIImageView调整大小
});
});

所有这些都发生在 cellForRowAtIndexPath

我在这里遇到的问题是:

1.如何更新单元格的高度?考虑到单个单元格中可能存在许多图像。所以我需要在下载时更改底部图像的位置。

2.我尝试使用 UITableView beginUpdates endUpdates ,但滚动到单元格的顶部会给用户带来糟糕的体验。



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



►在 GitHub 以及有关 Swift的其他详细信息食谱


I am displaying some text and images in a UITableView. The image first gets downloaded. Since before the image gets downloaded, I don't know the size of image, so I initially put a UIImageView of some fixed size. And when the image is downloaded, I resize the UIImageView.

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// Download image

    dispatch_async(dispatch_get_main_queue(), ^{

    // UIImageView resizing  
    });  
});

All this happens in cellForRowAtIndexPath.
The issues I am facing here are :
1. How do I update the height of cell ? Considering that there can be many images in a single cell. So I need to change the position of bottom image when above one downloads.
2. I tried using UITableView beginUpdates and endUpdates, but that scrolls to the top of cell giving a poor user experience.

This is how the UI looks like on reloadData. There are 5 images to be downloaded : UI experience after UITableView reloadData

解决方案

Short Answer

  • Give enough breathing space to estimatedRowHeight
  • Changing a UITableViewCell once returned by dequeueReusableCellWithIdentifier will not work with cached cells
  • Trigger a single cell reload with reloadRowsAtIndexPaths
  • Manage your cache with Core Data and let NSFetchedResultsController boilerplate code can do all the UI work.

In Details

No unexpected scroll, only updates images as they come:

  1. If the cell being refreshed is at or below the horizon, the UITableView will not scroll
  2. if the cell being refreshed is above the top, the UITableView will not scroll
  3. the UITableView will only scroll when the cell is in plain sight, and requires more space than available.

Let UITableViewAutomaticDimension do the hard work

You need to tell Cocoa Touch that the cell is stale, so that it will trigger a new dequeueReusableCellWithIdentifier, to which you are going to return a cell with the proper height.
Short of reloading the entire table view or one of its section, and assuming that your indexes are stable, invoke -tableView:reloadRows:at:with: passing the indexPath of the cell that just changed, and a .fade animation.

Code:

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

Use URLSession. When an image becomes available, 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 // 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()
}

Once in the cache, cellForRow merely reads into it from the UI thread:

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
}


Example: fetch a random set of images from *Wikipedia*

► Find this solution on GitHub and additional details on Swift Recipes.

这篇关于图像下载后更新单元格高度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆