2017-09-13 8 views
1

我有一个应用程序从API下载JSON数据并将其设置在tableview单元格中。在随机向上/向下滚动细胞图像的某个时候,在它有一个正确的图像之前,它可能会自行改变几次。没有任何问题的文本数据。起初我认为问题是细胞的可重用性,所以我需要在实际设置新图像之前销毁数据。所以我加了TableViewCell的这种方法cellForRowAt路径设置单元格之前销毁数据:可重复使用的单元格或错误的异步图像从TableView中的JSON数据下载

func destroyCellData() { 

    self.newsImageView.image = nil 
    self.newsTitleLabel.text = nil 
    self.tagLabel.text = nil 
} 

那么实际的方法设置单元格:

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

    guard let cell = tableView.dequeueReusableCell(withIdentifier: "newscell") as? NewsTableViewCell else { 

     print("No such cell") 
     exit(14) 
    } 

    cell.loadingImageIndicator.startAnimating() 

    let data = dataManager.getData() 

    let dataToInsert = data[indexPath.row] 
    cell.destroyCellData() 
    cell.setDataToCell(with: dataToInsert) 

    return cell 
} 

和方法setDataToCell是:

func setDataToCell(newsObject: jsonNews) { 

     self.newsTitleLabel.text = newsObject.title 
     self.tagLabel.text = newsObject.tag 

     let url = newsObject.imageURL 
     self.newsImageView.loadImageUsingCacheWithURLString(url, placeholder: UIImage(named: "ViewPlaceholder"), indicator: loadingImageIndicator) 

} 

最后我加载单元格内的异步图像:

let imageCache = NSCache<NSString, UIImage>() 

extension UIImageView { 

func loadImageUsingCacheWithURLString(_ URLString: String, placeholder: UIImage?, indicator: UIActivityIndicatorView? = nil) { 

    self.image = nil 

    if let cachedImage = imageCache.object(forKey: NSString(string: URLString)) { 

     self.image = cachedImage 
     indicator?.stopAnimating() 
     return 

    } 

    guard let encodedString = URLString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { 

     print("Error Loading URL") 
     return 
    } 

    if let url = URL(string: encodedString) { 

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

      if error != nil { 

       print("ERROR LOADING IMAGES FROM URL: \(String(describing: error))") 

       OperationManager.UI { 

        self.image = placeholder 
        indicator?.stopAnimating() 
       } 

       return 
      } 

       if let data = data { 

        if let downloadedImage = UIImage(data: data) { 

          print(URLString) 
          imageCache.setObject(downloadedImage, forKey: NSString(string: URLString)) 

         OperationManager.UI { 

          self.image = downloadedImage 
          indicator?.stopAnimating() 
        } 
       } 
      } 
     }).resume() 
    } 
} 

}

所以我有问题是 - 问题出在哪里我下载和设置图像的方法或是单元格的可重用性的问题?如果可能的话,给我一个更适合将图像设置为单元格的方式。在此先感谢

+0

正确的图像被替换为不正确的图像? – ColdLogic

+0

@ColdLogic是的,但它偶尔出现,最终在滚动tableview时被替换为正确 –

+0

查看此链接中的扩展名:https://github.com/antonio081014/TwitterPractice/blob/master/TwitterPractice/Helper/Extensions .swift 用存储正确url字符串的字符串变量创建子类,然后当收到图像数据时,检查是否收到正确的图像。 –

回答

0

没有你的代码,我怀疑你的问题可能与可重用单元格和异步图像下载。在这种情况下,当你重新加载单元格时,它会启动一个数据任务来下载图像,如果第二个任务开始下载不同的图像,则第一个没有任何反应。

例如,假设您的第一张图片为100MB,reusabel单元格的第二张图片为1KB。希望1KB下载速度更快。这里是流动

  1. 称重传感器与image1
  2. image1
  3. 称重传感器开始下载与image2
  4. image2
  5. image2
  6. 设置单元格图像的完整下载开始下载到image2
  7. 完成下载o ˚Fimage1
  8. 设置单元格图像image1

由于下载图像1图像2之后完成的数据任务已经设定,电池将得到更新,以显示此搜索它显示图像2后,从而显示错误图片。

要解决您的问题,您需要先取消第一个操作,或者更确切地说,如果图像视图不再显示该数据,则不更新图像视图。有很多方法可以做到这一点。一种解决方案是在您的单元格上创建图像url的属性,并在下载完成时,确认其正确的url,如果是,则更新图像视图。

func setDataToCell(newsObject: jsonNews) { 
    // Your other code 
    self.imageURL = newsObject.imageURL 
} 

// loadImageUsingCacheWithURLString 
if let downloadedImage = UIImage(data: data) { 

    print(URLString) 
    imageCache.setObject(downloadedImage, forKey: NSString(string: URLString)) 

    OperationManager.UI { 
     if url.absoluteString == self.imageURL { 
      self.image = downloadedImage 
      indicator?.stopAnimating() 
     } 
    } 
} 

注:没有测试此代码的任何,并写了直接从我的大脑。它可能有错误。

综上所述,我推荐使用第三方图像缓存系统,如AlamofireImage或其他人已经评论过的其中一个。

+0

SDWebImage https://github.com/rs/SDWebImage,可能是一个选项。 –

+0

非常感谢!这绝对是一个问题,所以我用一个带有urlString属性的customUIImageView来解决它。图像加载速度较慢,但​​在tableViewCells中没有冲突。而我并没有使用Alamofire的目的 - 弄清楚究竟是如何工作,并建立自己的模板进一步工作,并更好地了解这样的框架的架构 –

+0

@IhorDemchenko很高兴你得到它的工作! – ColdLogic

-1

您可以使用https://github.com/onevcat/Kingfisher异步图像加载。这照顾缓存和渲染正确的图像相应的索引

+0

与其他假解决方案相同的问题 - 您的链接是关于异步图像加载和缓存,但不支持单元格中的图像 - 您需要添加你自己的代码 – Gargo

相关问题