gpt4 book ai didi

ios - 在可重复使用的单元格中显示下载进度

转载 作者:搜寻专家 更新时间:2023-11-01 05:47:25 26 4
gpt4 key购买 nike

我正在尝试在我的 collectionview 单元格中显示下载进度。我目前正在使用具有单元格实例并更新进度条的解析进度 block 。

}, 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
}
}
})

所以这工作正常,我现在遇到的问题是,如果我离开这个 View Controller ,然后回来查看下载情况,单元格的实例已被重用,并且没有任何所需的 UI 元素可见,但进度仍在滴答作响。

我认为唯一可以重新显示 UI 元素的地方是 cellForItemAt。那么问题是进度不会更新,它只显示重新加载单元格时的值。

我怎样才能重新使用进度 block 正在使用的单元格实例或干净地显示继续更新的 ui 元素?

最佳答案

假设您要用 Collection View 关闭旧 View Controller 并呈现一个新 View Controller ,这里有两个问题:

  • 然后您将尝试更新前一个 View Controller 中 Collection View 中的单元格;和

  • 您正在保留对已关闭的旧 View Controller 的强引用。

如果是这种情况,目标是将进度更新与任何特定的 View Controller 、 Collection View 或单元分离。您可能还想分离项目/行号,以防您随时插入/删除任何单元格。处理此问题的最佳方法是通知:

  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 的引用,这可以防止进度 block 卡在您的 View Controller 上。

  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 与您首次创建下载时的内容分离很重要,以防您随时从 Collection View 中插入/删除任何项目。)

    现在,您可能会问应该使用什么作为标识符。您可以使用 URL 的 absoluteString。您可能会使用其他一些唯一标识符。但我不鼓励您仅依赖项目/行号,因为这些可能会改变(也许现在不会,但以后当您使应用程序变得更加复杂时,您可能会插入和删除项目)。

  4. 让您的 Collection View 的 View Controller 将自己添加为该通知的观察者,更新适当的进度 View :

    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] 捕获列表,以确保通知观察者不会导致与 View Controller 的强引用循环。

关于ios - 在可重复使用的单元格中显示下载进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42181912/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com