簡體   English   中英

在可重用單元格中顯示下載進度

[英]Displaying download progress in reusable cells

我試圖在我的collectionview單元中顯示下載進度。 我目前正在使用具有進度條的解析進度塊,並更新進度條。

}, progressBlock: { (percent) in
    self.mainQueue.addOperation {

    // set the downloadProgess var to update from cellForItemAt
    // downloadProgress = (Float(percent) / Float(100))

    if let downloadingCell = self.collectionView.cellForItem(at: self.indexPath) as? InnerCollectionCell {
        downloadingCell.progressBar.isHidden = false
        downloadingCell.contentView.bringSubview(toFront: downloadingCell.progressBar)
        downloadingCell.progressBar.setProgress(Float(percent) / Float(100), animated: true)
        downloadingCell.setNeedsDisplay()
        downloadingCell.setNeedsLayout()
        downloadingCell.isUserInteractionEnabled = false
        downloadingCell.spinner.isHidden = true
    }
}
})

所以這很好用,我現在遇到的問題是,如果我離開該視圖控制器,然后回來查看下載的進展情況,則該單元的實例已被重用,並且沒有所需的UI元素可見,但進度仍在滴答作響在后台。

我能想到的重新顯示UI元素的唯一位置是cellForItemAt。 然后的問題是進度不會更新,它只顯示重新加載單元時的值。

我該如何重用進度塊正在使用的單元格實例或干凈顯示繼續更新的ui元素?

假設您要用集合視圖關閉舊的視圖控制器並顯示一個新的視圖控制器,這里有兩個問題:

  • 然后,您嘗試在以前的視圖控制器中更新集合視圖中的單元格;

  • 您對被關閉的舊視圖控制器保持着強烈的參考。

在這種情況下,目標是將進度更新與任何特定的視圖控制器,集合視圖或單元分離。 您也可能還希望將項目/行號解耦,以防您隨時插入/刪除任何單元格。 最好的處理方法是通知:

  1. 定義在定義通知時使用的一些常量:

     private let notificationName = Notification.Name(rawValue: "com.domain.app.downloadProgress") private let notificationIdentifierKey = "com.domain.app.download.identifier" private let notificationPercentKey = "com.domain.app.download.percent" 
  2. 讓您的progressBlock發布通知,而不是嘗試直接更新UI:

     let percent: Float = ... let userInfo: [AnyHashable: Any] = [ notificationIdentifierKey: identifier, notificationPercentKey: percent ] NotificationCenter.default.post(name: notificationName, object: nil, userInfo: userInfo) 

    請注意,這里沒有對self引用,這使進度塊無法掛接到視圖控制器上。

  3. 定義一些函數,您可以用來識別哪個IndexPath與您的下載標識符相對應。 在我的簡單示例中,我將擁有一系列下載標識符,並使用該標識符:

     var downloadIdentifiers = [String]() private func indexPath(for identifier: String) -> IndexPath? { if let item = downloadIdentifiers.index(of: identifier) { return IndexPath(item: item, section: 0) } else { return nil } } 

    您可能有一個下載標識符作為某些Download模型對象的屬性,而是使用了它,但希望它能說明這一思想:只需有某種方法IndexPath以為給定的下載標識適當的IndexPath (順便說一句,如果您隨時從集合視圖中插入/刪除任何項目,將IndexPath與首次創建下載時的狀態脫鈎非常重要。)

    現在,您可能會問應該使用什么作為標識符。 您可以使用URL的absoluteString 您可以使用其他一些唯一標識符。 但我不鼓勵您僅依賴項目/行號,因為這些可能會更改(也許不是現在,但是可能稍后,當您使應用程序變得更加復雜時,您可能會插入刪除項目)。

  4. 讓您的集合視圖的視圖控制器將自身添加為該通知的觀察者,從而更新適當的進度視圖:

     private var observer: NSObjectProtocol! override func viewDidLoad() { super.viewDidLoad() observer = NotificationCenter.default.addObserver(forName: notificationName, object: nil, queue: .main) { [weak self] notification in if let identifier = notification.userInfo?[notificationIdentifierKey] as? String, let percent = notification.userInfo?[notificationPercentKey] as? Float, let indexPath = self?.indexPath(for: identifier), let cell = self?.collectionView?.cellForItem(at: indexPath) as? InnerCollectionCell { cell.progressView.setProgress(percent, animated: true) } } ... } deinit { NotificationCenter.default.removeObserver(observer) } 

    請注意[weak self]捕獲列表,以確保通知觀察者不會對視圖控制器造成強烈的引用周期。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM