ios - 在 UITableViewCell 中下载和缓存图像

标签 ios swift uitableview nscache

注意:请不要使用图书馆。这对我学习很重要。此外,对此有多种答案,但我发现没有一个能很好地解决问题。请不要标记为重复。提前致谢!

我遇到的问题是,如果您在表格中滚动得非常快,您会看到旧图像和闪烁。

  • 我阅读的问题的解决方案是取消 URLSession 数据请求。但我不知道如何在正确的地方做到这一点 和时间。可能还有其他解决方案,但不确定。

这是我目前所拥有的:

图片缓存类

class Cache {

    static let shared = Cache()

    private let cache = NSCache<NSString, UIImage>()
    var task = URLSessionDataTask()
    var session = URLSession.shared

    func imageFor(url: URL, completionHandler: @escaping (image: Image? error: Error?) -> Void) {
            if let imageInCache = self.cache.object(forKey: url.absoluteString as NSString)  {
                completionHandler(image: imageInCache, error: nil)
                return
            }

            self.task = self.session.dataTask(with: url) { data, response, error in

                if let error = error {
                    completionHandler(image: nil, error: Error)
                    return
                }

                let image = UIImage(data: data!)

                    self.cache.setObject(image, forKey: url.absoluteString as NSString)
                    completionHandler(image: image, error: nil)
                }

            self.task.resume()
    }
}

用法

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    let myImage = images[indexPath.row]

    if let imageURL = URL(string: myImage.urlString) {
        photoImageView.setImage(from: imageURL)
    }
    return cell
}

有什么想法吗?

最佳答案

swift 3:

可以通过这种方式避免闪烁:

public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

中使用以下代码
cell.photoImageView.image = nil //or keep any placeholder here
cell.tag = indexPath.row
let task = URLSession.shared.dataTask(with: imageURL!) { data, response, error in
    guard let data = data, error == nil else { return }

    DispatchQueue.main.async() {
        if cell.tag == indexPath.row{
            cell.photoImageView.image = UIImage(data: data) 
        }
    }
}
task.resume()

通过检查 cell.tag == indexPath.row,我们可以确保我们正在更改其图像的 imageview 与图像原本所在的行相同。希望对您有所帮助!

关于ios - 在 UITableViewCell 中下载和缓存图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44743591/

相关文章:

ios - 连续语音识别1分钟后无需重启

iphone - 使用 Storyboard 将 Window rootViewController 替换为另一个 View Controller

swift - 在 macOS Sierra 中使用 Quartz 事件模拟击键

objective-c - dequeueReusableCellWithIdentifier 总是返回 nil(不使用 Storyboard)

ios - 当我在 iOS 中滚动 UITableView 时,cellForRowAtIndexPath 无法正确显示单元格

ios - 没有 dequeueReusableCellWithIdentifier 的自定义 UITableViewCell

ios - UITextfield 的文本在填充后不会向左移动 - 因为我一直在输入

ios - 如何使用 Quartz 以 mmap() 方式对加密的 (AES-256) PDF 文件进行 "load"?

ios - Xcode UI 单元测试和权限警报

swift - Realm 写入阻塞主线程