当前位置: 首页 > 面试题库 >

在UITableViewCell中下载和缓存图像

柳绪
2023-03-14
问题内容

注意:请没有库。 这对我来说很重要。另外,对此有各种各样的答案,但我发现没有一个能很好地解决该问题。请不要将其标记为重复项。提前致谢!

我的问题是,如果您在表中快速滚动,会看到旧图像并闪烁。

  • 我所读问题的解决方案是取消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
}

有什么想法吗?


问题答案:

几个问题:

  1. 闪烁的一种可能来源是,当您异步更新图像时,您确实确实想先清除图像视图,因此您看不到重用/出列的表格视图单元格的前一行的图像。确保图像视图的设置image,以nil启动一个异步图像检索之前。或者,也许将其与您将在许多UIImageView同步图像检索类别​​中看到的“占位符”逻辑相结合。

例如:

    extension UIImageView {

    func setImage(from url: URL, placeholder: UIImage? = nil) {
        image = placeholder               // use placeholder (or if `nil`, remove any old image, before initiating asynchronous retrieval

        ImageCache.shared.image(for: url) { [weak self] result in
            switch result {
            case .success(let image):
                self?.image = image

            case .failure:
                break
            }
        }
    }
}
  1. 另一个问题是,如果您快速滚动,则重用的图像视图可能仍在进行旧的图像检索请求。实际上,当您调用UIImageView类别的异步检索方法时,应该取消与该单元格关联的先前请求。

这里的窍门是,如果在UIImageView扩展中执行此操作,则不能仅创建新的存储属性来跟踪旧请求。因此,您通常会使用“关联值”来跟踪先前的请求。



 类似资料:
  • 问题内容: 我有一个用代码创建的(没有): 在另一堂课中,我有一个扩展方法来下载图像异步: 我在其他地方使用了此功能并正常工作,根据我的日志,我了解到下载的图像没有问题(渲染单元时),下载图像后,单元UI未更新。 我也尝试使用像Haneke这样的缓存库,但是问题存在并且没有改变。 请帮助我理解错误 谢谢 问题答案: 设置图像后,您应该致电 编辑:从改正为

  • 图片下载和存取的简单demo。实现同步和异步两种下载方式。并且将下载好的图片保存在Document,然后进行读取显示。 [Code4App.com]

  • 问题内容: 有没有一种方法可以配置easy_install以避免安装失败时再次下载文件? 问题答案: pip(http://pypi.python.org/pypi/pip/)是easy_install工具的直接替代品,可以做到这一点。 只需运行并将环境变量设置为要pip存储文件的路径即可。请注意,缓存不适用于从源代码存储库(如svn / git / hg / bzr)中检出的依赖项。 然后使用代

  • 从阿卡迈加载的图像不会缓存在浏览器中。 通过开发者窗口查看时,我在标题中看到: 接受范围字节 访问控制允许信任。。。符合事实的 访问控制允许 访问控制请求他。。。X-request-With,内容类型,接受,来源 * Cache-Control max-age=0,无缓存,无存储 * 保持联系 内容长度114069 内容类型图像/jpeg 日期2013年7月2日星期二14:20:52 GMT Et

  • 问题内容: 我和我的朋友们在一个网站上工作,我们希望在其中缓存某些图像,以便将来更快地显示它们。我有两个主要问题: 您如何缓存图像? 图像被缓存后如何使用?(只是为了验证图像是否在页面A上缓存,可以从缓存中调用它以在页面B上使用它,对吗?) 此外,有可能设置 时, 图像的缓存版本将到期? 如果包括示例和/或进一步描述页面的链接,将不胜感激。 使用原始Javascript或jQuery版本都可以。

  • 将图片加载到纹理缓存中 因为Pixi用WebGL和GPU去渲染图像,所以图像需要转化成GPU可以处理的版本。可以被GPU处理的图像被称作 纹理 。在你让精灵显示图片之前,需要将普通的图片转化成WebGL纹理。为了让所有工作执行的快速有效率,Pixi使用 纹理缓存 来存储和引用所有你的精灵需要的纹理。纹理的名称字符串就是图像的地址。这意味着如果你有从"images/cat.png"加载的图像,你可以