【问题标题】:Images in tableview load another for a few seconds表格视图中的图像加载另一个几秒钟
【发布时间】:2018-09-20 00:39:16
【问题描述】:

我在 tableview 中有一个从 Json 下载的图像,一切正常,但是在看到相应图像之前滚动时,它会加载另一个图像几秒钟(这些图像是表格中已经可见的图像)。

我的数据结构是:

struct Data: Decodable {
    let name: String
    let img: String
    let phone: String
    let linktaller: String
    let web: String
}

我加载图片的单元格的代码是:

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



        guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? AseguradorasTableViewCell else { return UITableViewCell() }



        cell.titleLbl.text = company[indexPath.row].name
        .
        .
        .

         // load image
        if let imageURL = URL(string: company[indexPath.row].img) {
            DispatchQueue.global().async {
                let data = try? Data(contentsOf: imageURL)
                if let data = data {
                    let image = UIImage(data: data)
                    DispatchQueue.main.async {
                        cell.myImage.image = image


                    }
                }
            }

        }

        return cell

 }

加载数据的函数是:

    func downloadJSON() {

        let url = URL(string: "http://myserver.com/data.json")

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

            if error == nil {
                do {
                    self.company = try JSONDecoder().decode([Data].self, from: data!)

                    print(self.company)
                        DispatchQueue.main.async {
                        self.tableView.reloadData()
                        self.refreshControl.endRefreshing()
                    }

                } catch let jsonError{
                    print("error + \(jsonError)")
                }
            }
            }.resume()

   }

查看图片了解更多详情:

欢迎任何建议来解决这个问题。

【问题讨论】:

    标签: ios swift uitableview tableview


    【解决方案1】:

    在 UITableView dequeueReusableCell- 每个 UITableViewCell 将被多次使用不同的数据(图像)。 在您的情况下,每个cellForRowAt 被调用,图像将从服务器加载,因此会有延迟。 解决方案:图片加载完成后,必须在本地应用中缓存带有url的图片。
    (1)- 使用 SDWebImage - 支持缓存
    (2)- 您可以将图像保存在数组中 -> 在cellForRowAt 中,如果存在则从该数组加载,如果不存在则从服务器加载

    (图片来自网络)

    【讨论】:

      【解决方案2】:

      为缓存图像支持添加以下类:

      class ImageLoader {
      
          var cache = NSCache<AnyObject, AnyObject>()
      
          class var sharedInstance : ImageLoader {
              struct Static {
                  static let instance : ImageLoader = ImageLoader()
              }
              return Static.instance
          }
      
          func imageForUrl(urlString: String, completionHandler:@escaping (_ image: UIImage?, _ url: String) -> ()) {
              let data: NSData? = self.cache.object(forKey: urlString as AnyObject) as? NSData
      
              if let imageData = data {
                  let image = UIImage(data: imageData as Data)
                  DispatchQueue.main.async {
                      completionHandler(image, urlString)
                  }
                  return
              }
      
              let downloadTask: URLSessionDataTask = URLSession.shared.dataTask(with: URL.init(string: urlString)!) { (data, response, error) in
                  if error == nil {
                      if data != nil {
                          let image = UIImage.init(data: data!)
                          self.cache.setObject(data! as AnyObject, forKey: urlString as AnyObject)
                          DispatchQueue.main.async {
                              completionHandler(image, urlString)
                          }
                      }
                  } else {
                      completionHandler(nil, urlString)
                  }
              }
              downloadTask.resume()
          }
      }
      

      在单元格中,加载图片如下:

              // Load image
              let fimage = company[indexPath.row].img
      
              ImageLoader.sharedInstance.imageForUrl(urlString: fimage, completionHandler: { (image, url) in
                  if image != nil {
      
                      cell.myImage.image = image
      
                  }
              })
      

      这样,图像的下载应该可以正常工作了

      【讨论】:

        【解决方案3】:

        因为当单元格显示时,您从互联网下载图像

        let data = try? Data(contentsOf: imageURL)
        

        你应该

        1. 检查imageURL中的图片是否缓存
        2. 如果缓存,则从本地加载图像
        3. 如果不缓存,从互联网下载,然后缓存。

        或者只是简单地使用SDWebImage 或其他任何东西,它会自动为您检查步骤 1 到 3:D

        例如通过使用 SDWebImage

        import SDWebImage
        
        imageView.sd_setImage(with: URL(string: "your_image_url"))
        

        【讨论】:

          【解决方案4】:

          这是一个经典的单元重用问题。在开始下载之前,您应该在 tableView(cellForRowAt:) 方法中的每个单元格的图像视图中安装一个占位符图像或 nil。这将清除之前安装到单元格中的图像,然后异步下载可以在后台运行并在完成加载后安装图像。

          【讨论】:

            【解决方案5】:

            为了解决类似的问题,我更改了我的代码以协调图像的下载与 tableView 单元格的创建,将图像存储在本地数组中。

            我创建了一个字典数组来保存下载的图像,使用 url 字符串作为键:

            imagesArray = [String:UIImage]()

            然后,在代码中每个图像完成下载的位置,我将图像添加到数组中,并在 tableView 中插入一个新行:

            imagesArray.updateValue(UIImage(data: data!)!, forKey: imageURL as!String)

            tableView.beginUpdates()

            tableView.insertRows(at:[IndexPath(row: imagesArray.count-1, section: 0)], with: .automatic)

            tableView.endUpdates()

            tableView.reloadData()

            我还为每个图像维护一个单独的信息元素数组,包括图像 url 字符串作为一个元素。这允许我在 tableView 单元格中显示正确的项目:

            cell.itemNameLabel.text = itemRecords[indexPath.row].itemName
            cell.itemImage.image = imagesArray[itemRecords[indexPath.row].imageURL]

            在下载图像时,我展示了一个进度指示器微调器。

            一旦图像全部下载并加载到 imagesArray 中,当用户上下滚动以查看列出的单元格时,呈现不会有延迟,并且重用的单元格会加载正确的图像。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2022-12-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多