NSCache第一次加载时不适用于所有图像

dan*_*anu 5 ios nscache swift swift3

我正在使用swift 3.0中的一个项目,我通过使用NSCache来缓存来自服务器的响应,以便在UITableView中填充它们.然而由于某种原因,我只看到第一次加载应用程序时加载的图片很少,但如果我滚动并返回我看到的一切(从服务器检索响应的结束我也重新加载我的tableview,但似乎不是这样).我不确定我在这里错过了什么,代码如下所示,以显示我如何缓存图像.

let imageCache = NSCache<AnyObject, AnyObject>()
var imageURLString : String?

extension UIImageView {


    public func imageFromServerURL(urlString: String) {
        imageURLString = urlString

        if let url = URL(string: urlString) {

            image = nil


            if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage {

                self.image = imageFromCache

                return
            }

            URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in

                if error != nil{
                    print(error as Any)


                    return
                }

                DispatchQueue.main.async(execute: {

                    if let imgaeToCache = UIImage(data: data!){

                        if imageURLString == urlString {
                            self.image = imgaeToCache
                        }

                        imageCache.setObject(imgaeToCache, forKey: urlString as AnyObject)// calls when scrolling
                    }
                })
            }) .resume()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

3st*_*nt3 8

我认为这是一种更好的方法,使用子类而不是扩展,(从Jageen的注释中获取帮助,因为我们不能在扩展中包含存储的属性,所以我们使用封装的想法)

let imageCache = NSCache<AnyObject, AnyObject>()


    class CustomImageView: UIImageView {

            var imageUrlString: String?
            func loadImageUsingUrlString(_ urlString: String) {
                    let url = URL(string: urlString)
                    imageUrlString = urlString
                    image = nil

                    if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
                            self.image = imageFromCache
                            return
                    }

                    URLSession.shared.dataTask(with: url!) { (data, response, error) in
                            if error != nil {
                                    print(error!)
                                    return

                            }

                            DispatchQueue.main.async {

                                    let imageToCache = UIImage(data: data!)
                                    if self.imageUrlString == urlString {
                                           self.image = imageToCache  
                                    }
                                    imageCache.setObject(imageToCache!, forKey: urlString as AnyObject)

                            }

                            }.resume()

            }
    }
Run Code Online (Sandbox Code Playgroud)

- 现在使用此子类作为您在屏幕上显示的imageViews的类型

  • 这对我来说非常合适,还有来自Brian Voong youtube家伙的指导! (2认同)

Pm *_*Abi 3

这里图像正在下载并存储在缓存中。问题出在tableview单元格的更新上。

当表格视图将单元格加载到表格上时,图像尚未下载。但是一旦下载了图像,我们就必须有选择地更新单元格,以便立即显示图像。

由于您正在滚动,表格视图再次调用“cellForRowatIndexpath”,这会在滚动时更新显示下载图像的单元格。

如果您仍然希望使用扩展,我建议您添加 tableView 和 indexpath 作为参数,以便我们可以调用重新加载特定行并立即更新视图。

我已经更新了扩展中定义的表重新加载代码和函数结构。让我知道事情的后续。

let imageCache = NSCache<AnyObject, AnyObject>()
var imageURLString : String?

extension UIImageView {


public func imageFromServerURL(urlString: String, tableView : UITableView, indexpath : IndexPath)) {
    imageURLString = urlString

    if let url = URL(string: urlString) {

        image = nil


        if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage {

            self.image = imageFromCache

            return
        }

        URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in

            if error != nil{
                print(error as Any)


                return
            }

            DispatchQueue.main.async(execute: {

                if let imgaeToCache = UIImage(data: data!){

                    if imageURLString == urlString {
                        self.image = imgaeToCache
                    }

                    imageCache.setObject(imgaeToCache, forKey: urlString as AnyObject)// calls when scrolling

    tableView.reloadRows(at: [indexpath], with: .automatic)

                }
            })
        }) .resume()
    }
}
Run Code Online (Sandbox Code Playgroud)