0

我通過調用異步網絡任務,爲每個需要在UITableView中顯示的單元格下載圖像。這是UIViewController類表:在相應的單元格中下載並顯示圖像

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    guard results.count > 0 else { 
     return UITableViewCell() 
    } 

    let myCell = tableView.dequeueReusableCell(withIdentifier: CustomCell.cellIdentifier, for: indexPath) as! CustomCell 
    let model = results[indexPath.row] 
    myCell.model = model 
    return myCell 
} 

這是CustomCell

class CustomCell: UITableViewCell { 

// Several IBOutlets 

static let cellIdentifier = "myCell" 
let imageProvider = ImageProvider() 

var model: MyModel? { 
willSet { 
    activityIndicator.startAnimating() 
    configureImage(showImage: false, showActivity: true) 
} 
didSet { 
    guard let modelUrlStr = model?.imageUrlStr, let imageUrl = URL(string: modelUrlStr) else { 
     activityIndicator.stopAnimating() 
     configureImage(showImage: false, showActivity: false) 
     return 
    } 

    imageProvider.getImage(imageUrl: imageUrl, completion: {[weak self] (image, error) in 
     DispatchQueue.main.async { 
      guard error == nil else { 
       self?.activityIndicator.stopAnimating() 
       self?.configureImage(showImage: false, showActivity: false) 
       return 
      } 

      self?.imageView.image = image 
      self?.activityIndicator.stopAnimating() 
      self?.configureImage(showCoverImage: true, showActivity: false) 
     } 
    }) 
} 
} 

override func awakeFromNib() { 
super.awakeFromNib() 
configureImage(showCoverImage: false, showActivity: false) 
} 

override func prepareForReuse() { 
super.prepareForReuse() 
model = nil 
} 

private func configureImage(showImage: Bool, showActivity: Bool) { 
// Update image view 
} 
} 

而且ImageProvider

class ImageProvider { 
var imageTask: URLSessionDownloadTask? 

func getImage(imageUrl: URL, completion: @escaping DownloadResult) { 
imageTask?.cancel() 

imageTask = NetworkManager.sharedInstance.getImageInBackground(imageUrl: imageUrl, completion: { (image, error) -> Void in 
    if let error = error { 
     completion(nil, error) 
    } else if let image = image { 
     completion(image, nil) 
    } else { 
     completion(nil, nil) 
    } 
}) 
} 
} 

由於細胞可以動態離隊和重複使用和下載是異步的,然後一個圖像可以在滾動時在每個單元格上重用,我是這樣確保每個單元格總是顯示其對應的im年齡?

編輯:不同的方法

是否適當,以保持在細胞模型中的參考?考慮正確的MVC體系結構。誰應該負責下載圖像?單元格(僅傳遞給URL而不是完整的模型對象),或者表視圖的視圖控制器(更新tableView:cellForRowAt:方法中的單元格中的圖像)?

回答

0
  1. 添加一個方法你ImageProvider,將允許您取消底層URLSessionDownloadTask。當單元即將被重用時調用此方法。爲此,請在您的單元格子類中覆蓋prepareForReuse()
  2. 有可能在任務重新發生時已經完成任務,但DispatchQueue.main.async模塊仍然排隊,並且會在發生單元重用後觸發。爲了緩解這種情況,您需要根據存儲在模型中的URL檢查已完成任務的URL。
+0

謝謝。我在想......實際上在單元中有模型是正確的嗎?這打破了MVC模式,對吧?我看過一些例子,像這樣做,將模型傳遞給單元格,並在那裏處理網絡下載,但將這樣的邏輯移動到表視圖的視圖控制器會更合適嗎? – AppsDev

+0

@AppsDev我會建議你做那些讓你感覺不那麼尷尬的事情。如果嚴格遵守架構模式會使您爲不明確的收益增加複雜性,我會說避免它。在你的例子中完成的東西在這種情況下可能是完全正確的。這取決於你的系統的結構。按照你的直覺感受:) – ivanmoskalev

相關問題