每个表视图单元一个计时器

我想点击表格单元格并启动计时器。 每个小区都应该有自己的计时器。 我已设法设置计时器但不是独立的,当我设置一个所有单元格设置。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let currentCell = tableView.cellForRow(at: indexPath) as! StaffTableViewCell if isRunning == false { currentCell.cellImageView.image = UIImage(data: UIImagePNGRepresentation(#imageLiteral(resourceName: "greendot"))!) timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in counter += 1 let hourPortion = String(format: "%02d", counter / 3600) let minutesPortion = String(format: "%02d", counter / 60) let secondsPortion = String(format: "%02d", counter % 60) //print("\(hourPortion):\(minutesPortion):\(secondsPortion)") timeTotal = "\(hourPortion):\(minutesPortion):\(secondsPortion)" currentCell.timerLabel.text = timeTotal isRunning = true } } tableView.reloadData() } func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) { timer.invalidate() isRunning = false let currentCell = tableView.cellForRow(at: indexPath) as! StaffTableViewCell if let data = UIImagePNGRepresentation(#imageLiteral(resourceName: "reddot")) { currentCell.cellImageView.image = UIImage(data: data) } tableView.reloadData() } 

我就是这样做的:

  • 创建一个结构来表示包含开始时间以及该行当前是否正在运行的每一行
  • 安排重复计时器0.5秒以计算Timer的抖动
  • 每次计时器触发时,都会更新具有“运行”计时器的可见行
 import UIKit struct TimerModel { private var startTime: Date? private var offset: TimeInterval = 0 var elapsed : TimeInterval { get { return self.elapsed(since:Date()) } } var isRunning = false { didSet { if isRunning { self.startTime = Date() } else { if self.startTime != nil{ self.offset = self.elapsed self.startTime = nil } } } } func elapsed(since: Date) -> TimeInterval { var elapsed = offset if let startTime = self.startTime { elapsed += -startTime.timeIntervalSince(since) } return elapsed } } class ViewController: UIViewController { @IBOutlet weak var tableview: UITableView! var timer: Timer? var timersActive = 0 let formatter: DateComponentsFormatter = { let formatter = DateComponentsFormatter() formatter.zeroFormattingBehavior = .pad formatter.allowedUnits = [.hour, .minute, .second] return formatter }() var timers = [TimerModel](repeating:TimerModel(), count:30) override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func elapsedTimeSince(_ startTime: Date) -> String { let elapsed = -startTime.timeIntervalSinceNow return self.formatter.string(from: elapsed) ?? "0:00:00" } func startTimer() { self.timersActive += 1 guard self.timer == nil else { return } self.timer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] (timer) in if let me = self { for indexPath in me.tableview.indexPathsForVisibleRows ?? [] { let timer = me.timers[indexPath.row] if timer.isRunning { if let cell = me.tableview.cellForRow(at: indexPath) { cell.textLabel?.text = me.formatter.string(from: timer.elapsed) ?? "0:00:00" } } } } }) } func stopTimer() { self.timersActive -= 1 if self.timersActive == 0 { self.timer?.invalidate() self.timer = nil } } } extension ViewController: UITableViewDataSource { func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.timers.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) let timer = self.timers[indexPath.row] cell.imageView?.image = timer.isRunning ? #imageLiteral(resourceName: "GreenDot") : #imageLiteral(resourceName: "RedDot") cell.textLabel?.text = self.formatter.string(from: timer.elapsed) ?? "0:00:00" return cell } } extension ViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { self.timers[indexPath.row].isRunning = !self.timers[indexPath.row].isRunning self.tableview.reloadRows(at: [indexPath], with: .none) if self.timers[indexPath.row].isRunning { self.startTimer() } else { self.stopTimer() } } }