OriginalAlchemist
OriginalAlchemist

Reputation: 411

Swift : Pause and Resume NSTimer

I know this has been posted before, but I'm new to swift and i would like to find help as per my situation. So i need to run a timer, and when the stopMusic() is called(somewhere in my app), i need to pause the timer, then when the playMusic() is called, i need to resume the timer.

Here is what i have:

override func viewDidLoad() {

runFirstDropTimer = NSTimer.scheduledTimerWithTimeInterval(38.2, target: self, selector: "runAnimation", userInfo: nil, repeats: false)

}

func stopMusic() {
//Pause Timer
}

func playMusic() {
//Resume Timer
}

Thank you for any help you can provide!!!

Upvotes: 2

Views: 7169

Answers (2)

atereshkov
atereshkov

Reputation: 4555

Swift 5.

Resumable timer:

class ResumableTimer: NSObject {

    private var timer: Timer? = Timer()
    private var callback: () -> Void

    private var startTime: TimeInterval?
    private var elapsedTime: TimeInterval?

    // MARK: Init

    init(interval: Double, callback: @escaping () -> Void) {
        self.callback = callback
        self.interval = interval
    }

    // MARK: API

    var isRepeatable: Bool = false
    var interval: Double = 0.0

    func isPaused() -> Bool {
        guard let timer = timer else { return false }
        return !timer.isValid
    }

    func start() {
        runTimer(interval: interval)
    }

    func pause() {
        elapsedTime = Date.timeIntervalSinceReferenceDate - (startTime ?? 0.0)
        timer?.invalidate()
    }

    func resume() {
        interval -= elapsedTime ?? 0.0
        runTimer(interval: interval)
    }

    func invalidate() {
        timer?.invalidate()
    }

    func reset() {
        startTime = Date.timeIntervalSinceReferenceDate
        runTimer(interval: interval)
    }

    // MARK: Private

    private func runTimer(interval: Double) {
        startTime = Date.timeIntervalSinceReferenceDate

        timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: isRepeatable) { [weak self] _ in
            self?.callback()
        }
    }
}

Usage:

private var playTimer: ResumableTimer?

playTimer = ResumableTimer(interval: 5.0) { [weak self] in
   self?.doSomethingOnTimerFire()
}
playTimer?.start()

Upvotes: 7

Duncan C
Duncan C

Reputation: 131398

Short answer: You can't. Timers can't be paused.

Instead you need to record the current time when you start the timer:

let startTime = NSDate.timeIntervalSinceReferenceDate()
let interval = 38.2
//Start your timer 
runFirstDropTimer = NSTimer.scheduledTimerWithTimeInterval(interval, 
  target: self, 
  selector: "runAnimation", 
  userInfo: nil, 
  repeats: false)

Then, when you want to pause your timer, invalidate it and figure out how much time is left:

runFirstDropTimer.invalidate()
let elapsed = NSDate.timeIntervalSinceReferenceDate() - startTime
let remaining = interval - elapsed

And finally when you want to resume your timer create a new timer with the remaining value.

Upvotes: 6

Related Questions