table 单元格都有自己的进度视图非常慢

A table with cells that all have their own progress views is very slow

我有一个 table,它显示有关正在下载的对象列表的信息。每个单元格都包含一个 UIProgressView,它会根据该下载的进度进行更新。我的问题是,在这个进度视图的下载和更新过程中,一切都非常缓慢,并且 CPU 在 Xcode.

的调试导航器中监控到 100% 或更多

每个对象都存储了自己的进度属性。

class Download {
    var id: String = ""
    var progress: Float = 0
}

我有一个数组:

var downloads = [Download]()

这在我的视图控制器中使用 cellForRowAtIndexPath: 设置为 tableView,使用的内容如下:

let download = downloads[indexPath.row]
cell.progressView.progress = download.progress 

我正在使用 Alamofire 来管理我的下载并使用包含的进度关闭,我正在更新下载的进度:

download.progress = Float(bytesRead) / Float(bytesExpected)

dispatch_async(dispatch_get_main_queue()) {
    self.tableView.reloadData()
}

在这一点上,我认为由于发生大量更新而出现了瓶颈。为了限制问题,我尝试只更新一个单元格,因为它被更改了:

let rowIndex = self.downloads.indexOf() { [=15=].id == download.id }                 
let indexPath = NSIndexPath(forRow: rowIndex!, inSection: 0)

dispatch_async(dispatch_get_main_queue()) {
    self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}

但是我发现这会导致一切变得更慢。

如有任何建议,我们将不胜感激,提前致谢!

每秒可触发多次上传进度块,重新加载整个 table 视图既昂贵又低效。您应该做的是单独监控每个 table 视图单元格中的上传进度。这是你如何做到的。 在您的 tableviewcell 中:

  var progressTimer: NSTimer?

  var download: Download? {
    didSet {
      guard let download = download else {
        // cancel your timer here
        return
      }
      // start NSTimer here to update UIProgressView every second
    }
  }

  func prepareForReuse() {
    super.prepareForReuse()
    download = nil
  }

在您的视图控制器中:

override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,
    forRowAtIndexPath indexPath: NSIndexPath) {
      cell.download = downloads[indexPath.row]
  }

您正尝试在进度更新时重新加载 table 或单元格,这很繁重。

由于progressView已经创建,尝试复用它们,你可以使用Tag获得一个progressView实例:

    let rowIndex = self.downloads.indexOf() { [=10=].id == download.id }
    let indexPath = NSIndexPath(forRow: rowIndex, inSection: 0)


    let cell = tableView.cellForRowAtIndexPath(indexPath)

    let progressView = cell?.viewWithTag(100) // Tag your progressView as 100

    progressView.progress = download.progress

更进一步,您还可以通过每 0.5 秒或更短时间仅更新一次进度来调整性能,只要用户感觉进展顺利即可。但不是每一个 progressChanged,那样就太频繁了。