Search code examples
timerswiftnstimer

SWIFT - Multiple NSTimers


I have run in to a slight problem when trying to manage multiple NSTimers in SWIFT. No matter what I Try it will only ever invalidate the last timer I create. But I need to be able to invalidate any of the timers by choice.

Is there some way to create a reference ID that I could then use to select the specific NSTimer I want to invalidate? Any help would be great.

here is a snippet of my code.

import UIKit

var myTimer:NSTimer!

class TimerManager: NSObject {

}

public class Timer {
// each instance has it's own handler
private var handler: (timer: NSTimer) -> () = { (timer: NSTimer) in }

public class func start(duration: NSTimeInterval, repeats: Bool, handler:(timer: NSTimer)->()) {
    var t = Timer()
    t.handler = handler
    myTimer = NSTimer.scheduledTimerWithTimeInterval(duration, target: t, selector: "processHandler:", userInfo: nil, repeats: repeats)
}

@objc private func processHandler(timer: NSTimer) {
    self.handler(timer: timer)
}
}

class countdown{
//handles the countdown for the timer and invalidates when it reaches 0
var y = 0

func begin(length:Int) {

    y = length

    let delta = 1
    let delay = 1.0
    Timer.start(delay, repeats: true) {
        (t: NSTimer) in

        self.y -= delta
        println(self.y)

        if (self.y <= 0) {
            t.invalidate()
        }
    }
}

func end () {
    println("timer stopped")
    myTimer.invalidate()
}
}

And I create the timer like so:

 countdownTimer.begin(120) //time length in seconds ... 120 = 2 mins

To stop timer:

 countdownTimer.end() 

Solution

  • You may create a dictionary retaining NSTimer objects. Note that timerManager needs to be defined at global scope. Hope it shed light.

    class TimerManager {
    
        var _timerTable = [Int: NSTimer]()
        var _id: Int = 0
    
        /*! Schedule a timer and return an integer that represents id of the timer
         */
        func startTimer(target: AnyObject, selector: Selector, interval: NSTimeInterval) -> Int {
            var timer = NSTimer.scheduledTimerWithTimeInterval(interval, target: target, selector: selector, userInfo: nil, repeats: true)
            _id += 1
            _timerTable[_id] = timer
            return _id
        }
    
        /*! Stop a timer of an id
        */
        func stopTimer(id: Int) {
            if let timer = _timerTable[id] {
                if timer.valid {
                    timer.invalidate()
                }
            }
        }
    
        /*! Returns timer instance of an id
        */
        func getTimer(id: Int) -> NSTimer? {
            return _timerTable[id]
        }
    
    }
    
    // This needs to be delcared at global scope, serving as "singleton" instance of TimerManager
    let timerManager = TimerManager()
    

    Following code creates a new timer.

    var aTimer = timerManager.startTimer(self, selector: Selector("timerFunction"), interval: 1)
    

    To stop the timer, simply pass id to stopTimer(id: Int).

    /* Code ... */
    timerManager.stopTimer(aTimer)
    

    Also note getTimer method returns the actual instance with an id.

    Regards