user9911101
user9911101

Reputation:

Timer will reset and stop running during scrolling UITableView

timer.gif

↑↑↑↑↑↑↑↑↑ I show the problem in this GIF ↑↑↑↑↑

There is a timer and stratButton in the tableView cell, when I click the Button, the timeLabel will start running.

Now the problem is when I scroll the running timer out of the screen and scroll it back, the timer will reset and stop.

Hope someone can help me! I check many solution but they didn't work for me! I am almost cry.

my cellForRow:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! TimerTableViewCell

    cell.timer?.invalidate()
    let item = myTimerList[indexPath.row]
    cell.timerName.text = item.timerName
    cell.secondLeftLabel.text = "\(item.timerSecond)"      
    return cell

}

I created a small project contained my code for you to modify : https://app.box.com/s/axluqkjg0f7zjyigdmx1lau0c9m3ka47

Upvotes: 1

Views: 648

Answers (3)

Shehata Gamal
Shehata Gamal

Reputation: 100503

You need to preserve the state of each cell

class Service {

   static let shared = Service()

   var myTimerList = [TimerClass]()
}

//

here i added another 2 vars , why timerName is left despite you have to init them the same because current will hold the changing value

class TimerClass {

    let timerSecond : Int
    let timerName : String
    var current: Int
    var isPlaying = false

    init(second:Int, name:String) {

        timerSecond = second
        timerName = name
        current = second
     }

}

//

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! TimerTableViewCell


    let item = Service.shared.myTimerList[indexPath.row]
    cell.tag = indexPath.row // to access the array inside the cell
    if item.isPlaying {
      cell.play()     // add play method to the cell it has same button play action
    }
    else {
      cell.timer?.invalidate()
    }
    cell.timerName.text = item.timerName
    cell.secondLeftLabel.text = "\(item.current)"      
    return cell

}

//

inside the cell when the button is clicked , change isPlaying property to true and to false when stopped like this

// here self is the cell itself 

Service.shared.myTimerList[self.tag].isPlaying = true

also when the timer ticks change

Service.shared.myTimerList[self.tag].current = // value 

Upvotes: 1

Blerd
Blerd

Reputation: 56

Remove cell.timer?.invalidate() from cellForRowAt method, because every time you scroll the tableView this method is called to display new cells. In your case when you have started a timer for a cell and that cell is not in the view, next time you scroll to bring that cell again to the view cell.timer?.invalidate() causes it to stop.

Upvotes: 0

Ryan
Ryan

Reputation: 4884

You are reusing UITableViewCell. It means once cell is out of screen, it will be reused for the cell getting into the screen. Whenever it happens, it calls the delegate method - means cell.timer?.invalidate() is invoked again and again.

Upvotes: 0

Related Questions