2017-06-06 94 views
1

我試圖解決在Swift中以TableView異步下載圖像的問題。這是我的問題:我從一個網址異步下載圖像,但如果我快速滾動TableView,我的圖片開始旋轉(圖像交替顯示,直到出現正確的圖像)。Swift Image下載TableView

這是我的下載異步代碼和imageCache

let imageCache = NSCache() 

//DOWNLOAD Image ASINC 
extension UIImageView { 

    public func imageFromServerURL(url: String){ 

     if(imageCache.objectForKey(url) != nil){ 
      self.image = imageCache.objectForKey(url) as? UIImage 
     }else{ 

      let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration() 
      let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil) 
      let task = session.dataTaskWithURL(NSURL(string: url)!, completionHandler: { (data, response, error) -> Void in 
       if error == nil { 

        dispatch_async(dispatch_get_main_queue(), {() -> Void in 
         if let downloadedImage = UIImage(data: data!) { 
          imageCache.setObject(downloadedImage, forKey: url) 
          self.image = downloadedImage 
         } 
        }) 

       } 
       else { 
        print(error) 
       } 
      }) 
      task.resume() 
     } 

    } 
} 

和我TableView中回憶起這樣:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

     let cell = tableView.dequeueReusableCellWithIdentifier("record_charts", forIndexPath: indexPath) as! myTableViewCell 

      let url_img = "https://image/download.jpg" 
      cell.immagine.imageFromServerURL(url_img) 


     return cell 
    } 

這是向您展示問題更好 Gif Problem

+0

檢查此問題:https://stackoverflow.com/questions/15668160/asynchronous-downloading-of-images-for-uitableview-with-gcd。 –

+0

這是在對象c中,它不起作用... – mfiore

+0

你可以從這個問題得到你的問題的一般概念。 –

回答

1

這是由於iOS桌面視圖的重用機制。 你可以做一些修改代碼來解決這個問題:

class AsyncImageView: UIImageView { 

private var currentUrl: String? //Get a hold of the latest request url 

public func imageFromServerURL(url: String){ 
    currentUrl = url 
    if(imageCache.objectForKey(url) != nil){ 
     self.image = imageCache.objectForKey(url) as? UIImage 
    }else{ 

     let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration() 
     let session = NSURLSession(configuration: sessionConfig, delegate: nil, delegateQueue: nil) 
     let task = session.dataTaskWithURL(NSURL(string: url)!, completionHandler: { (data, response, error) -> Void in 
      if error == nil { 

       dispatch_async(dispatch_get_main_queue(), {() -> Void in 
        if let downloadedImage = UIImage(data: data!) { 
         if (url == currentUrl) {//Only cache and set the image view when the downloaded image is the one from last request 
          imageCache.setObject(downloadedImage, forKey: url) 
          self.image = downloadedImage 
         } 

        } 
       }) 

      } 
      else { 
       print(error) 
      } 
     }) 
     task.resume() 
    } 

} 
} 

注1:我是白板編碼的修改,因此,如果代碼中有正確的語法不知道。

注2:而不是聲明的UIImageView的一個新的子類,你可以使用相關對象。注意#3:我強烈建議你使用AlamoFireImage,它有一個UIImageView的類別,這正是你在這種情況下(以及未來的情況)所需要的。

1
的GIF

這是因爲電池重複使用。我會盡力解釋。假設您有10個單元,每個單元具有不同的圖像(圖像1到10),但只有5個單元適合屏幕。該表開始加載,第一個單元請求將圖像1放入圖像視圖中,並且該圖像開始在背景中發生,但在圖像的背景加載完成並且第一個單元格滾動屏幕之前滾動表格。現在細胞將被重新使用,讓我們說第六個細胞請求圖像6.您的圖像1的後臺請求,然後完成,因爲它仍然持有對細胞圖像的引用1放在圖像視圖。然後,圖像6的後臺進程完成,並用新版本替換圖像。如果圖像6在圖像1之前完成加載,則會更糟糕,因爲您將圖像6放入單元格中,然後將其替換爲圖像1.

您需要做的是實現某種方法,以便當圖像可用,你可以檢查它仍然是正確的使用。我不認爲你會這樣做,使該功能成爲ImageView的擴展,所以你可能需要某種中央圖像提供者或類似的東西。

0

您需要添加UIImageView擴展消除方法,並調用它或tableView(_:willDisplay:forRowAt:)prepareForReuse()UITableViewCell

,或者您可以取消請求,因爲SDWebImage的Web緩存