1

I am using a Timer to increment an Int and with a press of a button I record the current number in an array. I also have a TableView to show the contents of the array. Everything works fine, except that if I grab the TableView and move it even a bit to scroll, the Timer hangs until I release the TableView.

How can I keep the Timer running regardless of what I do to the TableView?

Here is my ViewController.swift:

import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var myTableView: UITableView!

    var timer = Timer()

    var isTimerOn = false

    var counter = 0

    var samples: [Int] = []

    override func viewDidLoad() {
        super.viewDidLoad()

        myTableView.dataSource = self
        myTableView.delegate = self
    }



    @IBAction func startStopButton(_ sender: Any) {
        switch isTimerOn {
        case true:
            timer.invalidate()
            isTimerOn = false
        case false:
            timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {_ in
                self.counter += 1
                print(self.counter)
            }
            isTimerOn = true
        }

    }

    @IBAction func recordButton(_ sender: Any) {
        samples.insert(counter, at: 0)
        myTableView.reloadData()
    }
}
extension ViewController {
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return samples.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! MyCell

        cell.number = samples[indexPath.row]

        return cell
    }
}

If you need it you can see the whole project on: https://github.com/Fr3qu3ntFly3r/TimerTest

Thank you for the help in advance.

Balazs Szamody
  • 382
  • 3
  • 11
  • check this page https://stackoverflow.com/questions/29204229/countdown-timer-on-uitableviewcell-scrolling-laggy-issue-of-uitableview – Raksha Saini Jul 27 '17 at 04:59

3 Answers3

2

It happened since you use the scheduledTimer(timeInterval:invocation:repeats:) or scheduledTimer(timeInterval:target:selector:userInfo:repeats:) class method to create the timer and schedule it on the current run loop in the default mode.

When we scroll the UIScrollview or UITableview, the run loop on main thread will switch to UITrackingRunLoopMode, and execute tasks which are in the mode. That is why your task in Default run loop was regardless.

Then you release the table view, the run loop switches to default mode, the timer works fine back.

Adding your timer to RunLoop with commonModes will solve this issue.

RunLoop.current.add(timer, forMode: .commonModes)

.commonModes is a configurable group of commonly used modes. Associating an input source with this mode also associates it with each of the modes in the group.

Hope this could help you :)

Learn more:

Run Loops Docs

0

On thing that is wrong is

var timer = Timer()

At this point, you are creating a completely useless Timer object. What you should do, is to never have a Timer that isn't actually scheduled. So:

var timer = Timer?
// No variable isTimerOn

Then in the startStopButton:

if let timer = self.timer {
    timer.invalidate()
    self.timer = nil
} else {
    self.timer = Timer.scheduledTimer (... )
}
gnasher729
  • 51,477
  • 5
  • 75
  • 98
0

Swift 5

I created an app like When clicking the button in TableviewCell timer will increment by 1sec. Here adding GitHub code Find The Code

Sreekanth G
  • 658
  • 6
  • 13