【问题标题】:Avoid fetching image again when cell in view避免在查看单元格时再次获取图像
【发布时间】:2017-09-14 13:19:25
【问题描述】:

当表格行进入视图时,我设法让一些代码在获取 Instagram 图片(通过 Alamofire)的地方工作。但是,一旦获取,当表格行再次出现时,我不希望再次调用。如何避免这种行为?

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

    let url = places[indexPath.row].url
    if let c = cell as? PlaceTableViewCell {
        print("Downloading Image")
        Alamofire.request(url, method: .get).responseImage { response in
            guard let image = response.result.value else {
                print("Error downloading image")
                return
            }
            c.photoImageView.image = image
        }

    }
}

【问题讨论】:

    标签: ios swift swift3 alamofire alamofireimage


    【解决方案1】:

    如果您已经在使用AlamoFire,最简单的方法是AlamoFireImage。它内置了您可以使用的缓存机制。例如:

    let imageCache = AutoPurgingImageCache()
    
    let urlRequest = URLRequest(url: URL(string: "https://httpbin.org/image/png")!)
    let avatarImage = UIImage(named: "avatar")!.af_imageRoundedIntoCircle()
    
    // Add
    imageCache.add(avatarImage, for: urlRequest, withIdentifier: "circle")
    
    // Fetch
    let cachedAvatarImage = imageCache.image(for: urlRequest, withIdentifier: "circle")
    
    // Remove
    imageCache.removeImage(for: urlRequest, withIdentifier: "circle")
    

    对于您的具体情况,我们实际上可以做一些更简单的事情。 AlamoFireImage 包含一个为您的需要量身定制的UIImageView 扩展。如果图像已经下载,这应该从共享缓存加载图像。

    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    
        let url = places[indexPath.row].url
        if let c = cell as? PlaceTableViewCell {
            print("Downloading Image")
            c.photoImageView.af_setImage(withURL: url)
        }
    }
    

    您还可以使用一些可选参数来实现有用的附加功能,例如在图像加载或加载失败时使用占位符图像。

    c.photoImageView.af_setImage(withURL: url, placeholderImage: placeholderImage)
    

    或完成块

    c.photoImageView.af_setImage(withURL: url, completion: { response in
        guard let image = response.result.value else {
            print("Error downloading image")
            return
        }
        c.photoImageView.image = image
    })
    

    【讨论】:

    • 不应该是“httpbin.org/image.png”而不是“httpbin.org/image/png
    • 顺便说一句。不知道 AlamoFireImage,谢谢提醒 :)
    • 你介意告诉我如何做我所做的,但使用 AlamofireImage + 缓存。我自己尝试过一次,但由于某种原因无法启动
    • @Miknash 实际上是 https://httpbin.org/image/png 在这种情况下。只是测试图片的奇数网址哈哈。
    • 感谢您的澄清 :)
    【解决方案2】:

    我建议您使用一些第三方库(例如https://github.com/onevcat/Kingfisher)。这样一来,您就可以缓存图片,以后无需再次下载。

    但是,如果您不想使用更多第三方库,您可以创建图像数组并在下载后将其放入数组中。将数组实例化为与数据数组相同的大小。然后,您的代码将如下所示:

    override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    
        let url = places[indexPath.row].url
        if let c = cell as? PlaceTableViewCell {
            print("Downloading Image")
            if let image = arrayOfImages[indexPath.row] {
                c.photoImageView.image = image
            }
            else {
                Alamofire.request(url, method: .get).responseImage { response in
                    guard let image = response.result.value else {
                        print("Error downloading image")
                        return
                    }
                    c.photoImageView.image = image
                    self.arrayOfImages[indexPath.row] = image
                }
            }
        }
    }
    

    【讨论】:

    • 我喜欢这个建议。谢谢
    • 我想缺点是没有缓存,所有图像都需要在应用加载时再次检索?
    • 那是正确的——当你回到屏幕时你会再次下载它们。它是临时缓存而不是临时缓存
    • 你的逻辑对吗?您不需要检查数组中是否存在图像 url 吗?我在任何地方都看不到你这样做。
    • print("Downloading Image") 正下方 - 我保存图片
    猜你喜欢
    • 2018-09-09
    • 2019-06-27
    • 1970-01-01
    • 2016-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    相关资源
    最近更新 更多