将CADisplayLink与tableViewCells一起使用所需的指导

时间:2018-07-30 12:36:34

标签: ios swift uitableview timer progress-bar

我正在创建一个包含列表的应用程序,该列表将在一定时间内有效。为此,我在每个单元格上创建一个倒计时条动画。每个单元格都有其自己的自定义持续时间,此后单元格将显示“时间到”。该单元甚至在滴答到0时显示时间(以秒为单位),然后显示“ Time's Up”消息。

在此上方,有一个倒计时栏动画。我正在控制来自viewController的所有这些动画,而不是在customView单元中执行这些动画,因为单元的可重用性使计时器陷入困境。

我正在使用两个计时器:

  1. Timer():每1秒调用一次。这用于简单的秒倒计时。我正在使用包含两个变量durationTimewidth的struct类型数组。 width默认设置为400。 durationTime由用户设置。

    @objc func handleCountdown() {
    let arrayLength = duration.count
    var i: Int = 0
    var timeCount: Int = 0
    
    
    for  _ in 0..<arrayLength {
    
    
       let value = duration[i].durationTime - 1 //Decreasing the timer every second
       let indexPath = IndexPath(row: i, section: 0)
    
    
        if (value > 0)
        {
            duration[i].durationTime = value
            if let cell = listTableView.cellForRow(at: indexPath) as! listTableViewCell? {
                cell.testlabel.text = "\(value)"
            }
            //listTableView.reloadRows(at: [indexPath], with: .automatic)
            i = i + 1
        } else {
            if let cell = listTableView.cellForRow(at: indexPath) as! listTableViewCell? {
                cell.testlabel.text = "Time's Up"
            }
            i = i + 1
            timeCount = timeCount + 1
    
        }
    }
    
    if (timeCount == (arrayLength - 1)) {
        self.timer?.invalidate()
    }
    }
    

上面的代码每秒被调用一次。它递减时间的值,然后将其显示在表格视图单元格中。上面的代码可以正常工作。

  1. CADisplayLink:此计时器用于运行进度条动画。但是,在这种情况下,我要计算经过的时间,然后将其除以每个元素的durationTime并计算百分比。该百分比用于更新每个进度条的width的值。 (请记住,durationBar只是duration数组的重复项。但是,在该数组中,durationTime不会递减->仅用于测试目的)这是代码:

    @objc func handleProgressAnimation() {
    let currenttime = Date()
    let elapsed = currenttime.timeIntervalSince(animationStartDate)
    let totalWidth: Double = 400.0
    print(elapsed)
    let arrayLength = duration.count
    var i: Int = 0
    
    
    
    for  _ in 0..<arrayLength {
       let indexPath = IndexPath(row: i, section: 0)
       let percentage = (elapsed / Double(durationBar[i].durationTime))
       let newWidth = Double(totalWidth - (totalWidth * percentage))
        durationBar[i].width = newWidth
        if let cell = listTableView.cellForRow(at: indexPath) as! listTableViewCell? {
            cell.timeRemainingView.frame.size.width = CGFloat(durationBar[indexPath.row].width)
    
        }
        i = i + 1
    }
    
    }
    

问题:一段时间后,即使时间尚未完成,某些进度条也会从单元格中消失。一旦在tableview上进行了一些滚动,它就会经常发生。

这是willDisplayCellcellForRowIndexPath

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: cellid, for: indexPath) as! listTableViewCell
    return cell
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
   let cell:listTableViewCell = cell as! listTableViewCell
    cell.testlabel.text = "\(duration[indexPath.row].durationTime)"
    cell.timeRemainingView.frame.size.width = CGFloat(duration[indexPath.row].width)

}

如下面的图片所示,经过一段时间后,即使还有一些时间,进度条也消失了:

enter image description here

这里的问题是什么,我正在控制viewController而不是单元中的所有动画和计时器,以防止单元可重用性成为问题。需要帮助!

1 个答案:

答案 0 :(得分:0)

问题是您用{p>更新cell.timeRemainingView.frame.size.width

durationBar[indexPath.row].width代表handleProgressAnimation

duration[indexPath.row].width代表willDisplayCell

我也将切换到tableView.indexPathsForVisibleRows以仅针对可见单元格更新UI,这样它就不会为if-let中的每个单元格调用.cellForRow。