ios - 每個表視圖單元一個計時器



swift uitableview (1)

我想點擊表格單元格並啟動計時器。 每個小區都應該有自己的計時器。 我已設法設置計時器但不是獨立的,當我設置一個所有單元格設置。

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




cocoa-touch