2017-07-26 53 views
2

我在swift 3.0中的项目上工作,我使用NSCache缓存来自服务器的响应,将它们填充到UITableView中。然而,由于某种原因,我第一次看到应用程序加载时加载的图像很少,但如果如果我滚动并返回,我会看到所有内容(从服务器检索响应的结尾,我也重新加载了我的tableview,但看起来像不是这种情况)。我不知道我在这里完全错过了什么,代码如下,以显示我如何缓存图像。NSCache不适用于第一次加载时的所有图像

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() 
     } 
    } 
} 
+1

我的主要嫌疑人是imageURLString,因为它是全局变量,您将它与本地变量进行比较,但是您会为每个请求进行更改。 Y?确保这一点,为了什么你的目的,你写这个(如果imageURLString == urlString)是工作,因为你的期望和更多只是检查你的逻辑适用于只有一个图像? – Jageen

+0

我认为这段代码是正确的,并且图像需要时间来加载,因为它们来自服务器,我认为如果你不滚动图像将仍然加载 – 3stud1ant3

+0

否,如果我不滚动它不会炒锅:( – danu

回答

2

这里图像下载并存储在缓存中就好了。问题在于桌面单元的更新。

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

由于您正在滚动,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() 
    } 
} 
+0

我有一个示例项目,使用简单的swift 3进行json解析。您可以在这里参考: [link](https:// github。 com/PmAbi1993/Json-Parser) –

+0

太棒了!!就像一个魅力!! –

+0

但它会导致tableview滚动到顶部每次单元格加载。 –

5

我认为这将使用子类,而不是延长,是一种更好的方法(以从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() 

      } 
    } 

- 现在使用这个子类作为你在屏幕上显示的图像类型

+1

这对我来说非常合适,以及来自Brian Voong的YouTube用户的指导! –

相关问题