2017-01-23 50 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緩存代碼片段作爲例子 –