我正在创建一个应用程序,其中包含在一定时间内有效的列表。为此,我在每个单元格上创建一个倒计时条动画。每个单元格都有自己的自定义持续时间,在此之后单元格将显示“时间已到”。该单元格甚至会在滴答到 0 时显示以秒为单位的时间,然后显示“时间已到”消息。
在其正上方,有一个倒计时栏动画。我从 viewController 控制所有这些动画,而不是在 customView 单元中执行这些动画,因为单元可重用性使计时器变得困惑。
我使用两个计时器:
Timer()
:每 1 秒调用一次。这用于简单的秒倒计时。我正在使用一个结构体类型的数组,其中包含两个变量durationTime
和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() } }
上面的代码每秒都会被调用一次。它减少时间值,然后将其显示在表格 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 上进行一些滚动后,这种情况最常发生。
这是 willDisplayCell
和 cellForRowIndexPath
:
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)
}
正如下面的图片所示,一段时间后,即使还有一些时间,一些进度条也消失了:
这里有什么问题,我从 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/