ios - 将 CADisplayLink 与 tableViewCells 一起使用所需的指南

标签 ios swift uitableview timer progress-bar

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

在其正上方,有一个倒计时栏动画。我从 viewController 控制所有这些动画,而不是在 customView 单元中执行这些动画,因为单元可重用性使计时器变得困惑。

我使用两个计时器:

  1. Timer() :每 1 秒调用一次。这用于简单的秒倒计时。我正在使用一个结构体类型的数组,其中包含两个变量 durationTimewidth。默认情况下,宽度 设置为 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()
    }
    }
    

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

  • CADisplayLink:该计时器用于运行进度条动画。然而,在这种情况下,我计算耗时并将其除以每个元素的持续时间并计算百分比。该百分比用于更新每个进度条的宽度值。 (请记住,durationBar 只是持续时间数组的重复。但是,在此数组中,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
    }
    
    }
    
  • 问题:一段时间后,即使时间尚未完成,某些进度条也会从单元格中消失。当我在桌面 View 上进行一些滚动后,这种情况最常发生。

    这是 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 而不是单元控制所有动画和计时器,以防止单元可重用性成为问题。需要帮助!

    最佳答案

    问题是你更新了cell.timeRemainingView.frame.size.width

    durationBar[indexPath.row].width对于 handleProgressAnimation

    duration[indexPath.row].width对于 willDisplayCell .

    而且我还会切换到 tableView.indexPathsForVisibleRows 来仅更新可见单元格的 UI,这样它就不会为 if-let 中的每个单元格调用 .cellForRow。

    关于ios - 将 CADisplayLink 与 tableViewCells 一起使用所需的指南,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51594131/

    相关文章:

    objective-c - 如何做这种自定义 UITableView

    ios - Swift 中的 CATransform3DMakeRotation anchor 和位置

    ios - iPad UISplitViewController : Expand master instead of detail full screen?

    swift - 如何在 Swift 中重复播放音乐

    ios - Swift - 声明泛型数组

    uitableview - UIView-Encapsulated-Layout-Width/Height 约束为零

    ios - 快速地,在应用程序被杀死时将用户的当前位置发送到服务器

    ios - 如何将操作设置为搜索的取消按钮

    ios - 如何使用 Swift 5 通过相机仅扫描特定区域?

    ios - 在 UILabel 中检测 url