2017-01-23 21 views
1

林下载从JSON图像链接,然后创建图像,一旦表视图开始创建它的细胞:更新表格单元格图像异步

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

     let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCellController 

      DispatchQueue.main.async(execute: {() -> Void in 

       if let url = NSURL(string: self.movies[indexPath.row].image) 
       { 

        if let data = NSData(contentsOf: url as URL) 
        { 
         let imageAux = UIImage((data: data as Data)) 
         cell.movieImage.image = imageAux 
         self.tableView.reloadData() 

        } 
       } 
      }) 

     cell.name = self.movies[indexPath.row].name 
     cell.date = self.movies[indexPath.row].date 
     return cell 
} 

而且能正常工作,但表视图变得很慢,不是在渲染而是在滚动。我一直在检查内存和CPU,两者都非常低,但我的网络使用不断上升,但图像已经在单元上,所以它意味着它已经完成。 (对于这个测试即时调用JSON只有2部电影,所以2图像)

在我开始这样做之前,我总下载大约200kb(有图像),现在它超过2MB,然后停止项目。

什么即时做错了?

回答

3

您可能希望为后台活动指定一个单独的队列。在这种情况下,你的繁重的网络任务是:

NSData(contentsOf: url as URL)

这就是“冻结”的UI。最好的解决方法是定义像DispatchQueue.background和执行网络电话在那里,而后来执行UI任务背面的主线程上,以免锁定显示器:

DispatchQueue.background.async(execute: {() -> Void in 
    if let url = NSURL(string: self.movies[indexPath.row].image) { 
     //Do this network stuff on the background thread 
     if let data = NSData(contentsOf: url as URL) { 
      let imageAux = UIImage(data: data as Data) 
      //Switch back to the main thread to do the UI stuff 
      DispatchQueue.main.async(execute: {() -> Void in 
       cell.movieImage.image = imageAux 
      } 
     } 
    } 
}) 

让我知道,如果这说得通。

+0

非常感谢!另一个问题是,我不需要重新加载表格,它的图像下载了十几次(很明显,但我一开始并没有看到它)。 非常感谢迈克尔! – Adrian

+0

迈克尔福尔我知道这不是问题,但我知道我有一个问题,因为即时通讯使用dequeueReusableCell每次我向上或向下滚动单元格将再次下载图像,我怎么可以避免这种情况?谢谢! – Adrian

+2

我会将图像@Adrian缓存到'NSCache'文档中。这很容易使用。如果你发布另一个问题,我可以添加我的UIImage缓存代码片段作为例子 –

相关问题