代码之家  ›  专栏  ›  技术社区  ›  Osama Naeem

在tableViewCells中使用CADisplayLink所需的指导

  •  0
  • Osama Naeem  · 技术社区  · 7 年前

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

    在这上面,有一个倒计时条动画。我从viewController控制所有这些动画,而不是在customView单元中执行这些操作,因为单元的可重用性使计时器变得混乱。

    我用了两个定时器:

    1. Timer() :每1秒调用一次。这是用于简单的秒倒计时。我使用的是一个包含两个变量的struct类型数组 durationTime &安培; width . 这个 宽度 默认设置为400。这个 持续时间 由用户设置。

      @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()
      }
      }
      

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

    1. CADisplayLink :此计时器用于运行进度条动画。但是,在本例中,我计算经过的时间,并将其除以每个元素的持续时间,然后计算一个百分比。此百分比用于更新 宽度 每个进度条。(请记住,durationBar只是duration数组的副本。但是,在此数组中,持续时间不会减少->仅用于测试目的)下面是代码:

      @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上做了一些滚动之后,这种情况经常发生。

    这是 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)
    
    }
    

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

    enter image description here

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

    1 回复  |  直到 7 年前
        1
  •  0
  •   Eduard    7 年前

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

    durationBar[indexPath.row].width 对于 handleProgressAnimation

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

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

    推荐文章