Search code examples
iosswiftnstimer

How to set the timers in [NSTimer] to nil?


The goal is to fire timers when selecting a row in a tableView and in the same time getting rid of the old timers. As I don't want to leave anything in memory I guess invalidating them isn't enough. The new timers may be different (I've simplified the code here), so I don't want to re-use them.

I'm trying to set the timers in an array to nil but on the line timer = nil Xcode gives an error.

class DataModel() {
  var timers = [NSTimer]()
}

class TableViewController: UITableViewController {

  var dataModel = DataModel()

  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    if dataModel.timers.count != 0 {
      for timer in dataModel.timers {
        timer.invalidate()
        timer = nil  //"Cannot assign to value: timer is a let constant."
      }
    }

    for i in 0...10 {
      var timer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(i), target: self, selector: "doSomething", userInfo: nil, repeats: false)
      dataModel.timers.append(timer)
    }
  }    
}

I've tried making the timer instances optionals NSTimer? but that also does not work, I may be doing something wrong here in the for timer in dataModels.timer line. Would I need an if let construction?

class DataModel() {
  var timers = [NSTimer?]()
}

class TableViewController: UITableViewController {

  var dataModel = DataModel()

  override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    if dataModel.timers.count != 0 {
      for timer in dataModel.timers {
        timer!.invalidate()
        timer = nil // Error here
      }
    }

    for i in 0...10 {
      var timer = NSTimer?()
      timer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(i), target: self, selector: "doSomething", userInfo: nil, repeats: false)
      dataModel.timers.append(timer)
      //timer = nil // No error here.
    }
  } 
}

Setting dataModel.timers = [] certainly wouldn't be enough I guess, as it would just clear the array but leave the timer instances intact.

What would be the best way to solve this?


Solution

  • It is because you are in a loop, where you cannot mutate the object that is being iterated.

    for timer in timers {
        // timer is initialized here like "let timer = timers[index]"
    }
    

    Invalidate the the timers in the loop, then set

    timers = nil
    

    or

    timers.removeAll()