Swift:Pause and Resume Nstimer

How can I pause and resume NSTimer.scheduledTimerWithTimeInterval in swift?

You need to invalidate it and recreate it. You can then use an isPaused bool to keep track of the state if you have the same button to pause and resume the timer:

var isPaused = true
var timer = NSTimer()
@IBAction func pauseResume(sender: AnyObject) {
if isPaused{
timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("somAction"), userInfo: nil, repeats: true)
isPaused = false
} else {
timer.invalidate()
isPaused = true
}
}

Swift : Pause and Resume NSTimer

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.

Pausing and Resuming a Timer in iOS

I have a custom timer application and dealt with the same issue. There are many ways to address this. You may want to track pausedTime like you do elapsedTime and subtract that from your other variables. This gives you some flexibility as well to show totalTime vs. elapsedTime, etc... My function is quite a bit different, so I retrofitted it to your setup.

Basically, pausing is different because you can pause/resume multiple times. So you need to track previous pauses, and current pause state and subtract from elapsed time (or total time, or whatever you want).

I tested this code and it worked. Give it a try and let me know:

import UIKit

class TimedWorkoutViewController: UIViewController {

@IBOutlet weak var pauseButton: UIButton!
@IBOutlet weak var startButton: UIButton!

var startTime = NSTimeInterval()
var timer = NSTimer()
var isTiming = Bool()
var isPaused = Bool()
var pausedTime: NSDate? //track the time current pause started
var pausedIntervals = [NSTimeInterval]() //track previous pauses

override func viewDidLoad() {
super.viewDidLoad()

}

func updatedTimer() {
let currentTime = NSDate.timeIntervalSinceReferenceDate()
var pausedSeconds = pausedIntervals.reduce(0) { $0 + $1 } //calculate total time timer was previously paused
if let pausedTime = pausedTime {
pausedSeconds += NSDate().timeIntervalSinceDate(pausedTime) //add current pause if paused
}
var elapsedTime: NSTimeInterval = currentTime - startTime - pausedSeconds //subtract time paused
let minutes = Int(elapsedTime / 60.0)

elapsedTime -= (NSTimeInterval(minutes) * 60)
let seconds = Int(elapsedTime)

elapsedTime -= NSTimeInterval(seconds)

let strMinutes = String(format: "%02d", minutes)
let strSeconds = String(format: "%02d", seconds)

workoutTime.text = "\(strMinutes) : \(strSeconds)"
}

@IBAction func startButtonTapped(sender: AnyObject) {

if !timer.valid {

timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(TimedWorkoutViewController.updatedTimer), userInfo: nil, repeats: true)
startTime = NSDate.timeIntervalSinceReferenceDate()
}

isTiming = true
isPaused = false
pausedIntervals = [] //reset the pausedTimeCollector on new workout
}

@IBAction func pauseAndContinueButtonTapped(sender: AnyObject) {

if isTiming == true && isPaused == false {

timer.invalidate() //Stop the Timer
isPaused = true //isPaused
isTiming = false //Stopped Timing
pausedTime = NSDate() //asuuming you are starting a brand new workout timer
pauseButton.setTitle("RESUME", forState: UIControlState.Normal) //Set Button to Continue state

} else if isTiming == false && isPaused == true {

let pausedSeconds = NSDate().timeIntervalSinceDate(pausedTime!) //get time paused
pausedIntervals.append(pausedSeconds) // add to paused time collector
pausedTime = nil //clear current paused state

if !timer.valid {

timer.invalidate()
//timer = nil

timer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: #selector(TimedWorkoutViewController.updatedTimer), userInfo: nil, repeats: true)

}

isPaused = false
isTiming = true
pauseButton.setTitle("PAUSE", forState: UIControlState.Normal) //Set Button to Continue state

}

}
}

how to pause and resume NSTimer in iphone

You can't pause a timer. However, when the user goes to the settings view, you can save the fireDate of the timer and also the current date. After this you invalidate the timer and let the user do his/her stuff.
Once he/she switches back to the game, you create a new timer object and set the fire date to the old fire date plus the time the user was in the menu (oldTime + currentTime).

Swift NSTimer Pause Resume

You didn't pause the timer, you stopped it. If you read the documentation for invalidate, it says [emphasis added]:

Stops the receiver from ever firing again and requests its removal from its run loop.

Timers don't pause; it's simply not part of their API. If you want a pause/resume behavior, there are a variety of ways to get it, including:

  • Create a new timer when resuming.
  • Set the fireDate to Date.distantFuture when pausing, then set it to some time in the near future when resuming.
  • Use a boolean variable to indicate the paused state, and have your timer callback check that variable when the timer fires. If paused == true, do nothing.

ios8 Swift SpriteKit - Pause and Resume NSTimers in swift

There is a way to pause/resume Timer instances, because using repeating timers we know the next fire date.

This is a simple class SRTimer and a protocol SRTimerDelegate


Protocol SRTimerDelegate

protocol SRTimerDelegate : AnyObject {
func timerWillStart(_ timer : SRTimer)
func timerDidFire(_ timer : SRTimer)
func timerDidPause(_ timer : SRTimer)
func timerWillResume(_ timer : SRTimer)
func timerDidStop(_ timer : SRTimer)
}

Class SRTimer

class SRTimer : NSObject {

var timer : Timer?
var interval : TimeInterval
var difference : TimeInterval = 0.0
var delegate : SRTimerDelegate?

init(interval: TimeInterval, delegate: SRTimerDelegate?)
{
self.interval = interval
self.delegate = delegate
}

@objc func start(_ aTimer : Timer?)
{
if aTimer != nil { fire(self) }
if timer == nil {
delegate?.timerWillStart(self)
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(fire), userInfo: nil, repeats: true)
}
}

func pause()
{
if timer != nil {
difference = timer!.fireDate.timeIntervalSince(Date())
timer!.invalidate()
timer = nil
delegate?.timerDidPause(self)
}
}

func resume()
{
if timer == nil {
delegate?.timerWillResume(self)
if difference == 0.0 {
start(nil)
} else {
Timer.scheduledTimer(timeInterval: difference, target: self, selector: #selector(start), userInfo: nil, repeats: false)
difference = 0.0
}
}
}

func stop()
{
if timer != nil {
difference = 0.0
timer!.invalidate()
timer = nil
delegate?.timerDidStop(self)
}
}

@objc func fire(_ sender : SRTimer)
{
delegate?.timerDidFire(self)
}

}

Make your class conform to the protocol SRTimerDelegate and initialize a SRTimer instance with

var timer : SRTimer!
timer = SRTimer(interval: 5.0, delegate: self)

Methods

start() calls the delegate method timerWillStart and starts the timer.

pause() saves the difference between the current date and the next fire date, invalidates the timer and calls the delegate method timerDidPause.

resume() calls the delegate method timerWillResume, creates a temporary one shot timer with the saved difference time interval. When this timer fires the main timer will be restarted.

stop() calls the delegate method timerDidStop and invalidates the timer.

When the timer fires, the delegate method timerDidFire is called.

Pause NSTimer on home-button-press and start them again once the app is in foreground

Pausing of NSTimer is not a native feature in objective-c or swift. To combat this, you need to create an extension, which I happen to have created and will share for you. This will work for both OS X and iOS

import Foundation
import ObjectiveC

#if os(iOS)
import UIKit
#else
import AppKit
#endif

private var pauseStartKey:UInt8 = 0;
private var previousFireDateKey:UInt8 = 0;

extension NSTimer
{
private var pauseStart: NSDate!{
get{
return objc_getAssociatedObject(self, &pauseStartKey) as? NSDate;

}
set(newValue)
{
objc_setAssociatedObject(self, &pauseStartKey,newValue,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
}
}

private var previousFireDate: NSDate!{
get{
return objc_getAssociatedObject(self, &previousFireDateKey) as? NSDate;

}
set(newValue)
{
objc_setAssociatedObject(self, &previousFireDateKey,newValue,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN);
}
}

func pause()
{
pauseStart = NSDate();
previousFireDate = self.fireDate;
self.fireDate = NSDate.distantFuture() ;
}

func resume()
{
if(pauseStart != nil)
{
let pauseTime = -1 * pauseStart.timeIntervalSinceNow;
let date = NSDate(timeInterval:pauseTime, sinceDate:previousFireDate );
self.fireDate = date;
}

}
}

Then when you need to use it, simply call timer.pause() and timer.resume() You of course have to keep track of your timers in your gamescene object to do this, so make sure that timer is a variable accessible for the entire class, and when making your timer, you do timer = NSTimer.schedule...

At the beginning of your class:

var spawnBulletsTimer : NSTimer?;
var spawnMeteorsTimer : NSTimer?;
var onTimer: NSTimer?;

When creating the timers:

spawnBulletsTimer = NSTimer.scheduledTimerWithTimeInterval(0.2, target:     self, selector: Selector("SpawnBullets"), userInfo: nil, repeats: true)

spawnMeteorsTimer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("SpawnMeteors"), userInfo: nil, repeats: true)

onTimer = NSTimer.scheduledTimerWithTimeInterval(timeInterval, target: self, selector: Selector("onTimer:"), userInfo: nil, repeats: true)

Then when you need to pause:

onTimer?.pause() 
spawnBulletsTimer?.pause()
spawnMeteorTimer?.pause()

Then when you need to resume:

onTimer?.resume() 
spawnBulletsTimer?.resume()
spawnMeteorTimer?.resume()

How to Pause/Play NSTimer?

Try this shizzle... worked great for me

EDIT

To be honest my actual code is this:

-(IBAction)clicked:(id)sender
{
if ([startStop.titleLabel.text isEqualToString:@"Start"])
{
[startStop setTitle:@"Pause" forState:UIControlStateNormal];
[startStop setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(countUp) userInfo:nil repeats:YES];
timerDown = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(countDown) userInfo:nil repeats:YES];

} else if ([startStop.titleLabel.text isEqualToString:@"Pause"])
{
[startStop setTitle:@"Resume" forState:UIControlStateNormal];
[startStop setTitleColor:[UIColor colorWithRed:0/255 green:0/255 blue:255/255 alpha:1.0] forState:UIControlStateNormal];

pauseStart = [[NSDate dateWithTimeIntervalSinceNow:0] retain];
previousFireDate = [[timer fireDate] retain];
[timer setFireDate:[NSDate distantFuture]];

} else if ([startStop.titleLabel.text isEqualToString:@"Resume"])
{
[startStop setTitle:@"Pause" forState:UIControlStateNormal];
[startStop setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

float pauseTime = -1*[pauseStart timeIntervalSinceNow];
[timer setFireDate:[NSDate dateWithTimeInterval:pauseTime sinceDate:previousFireDate]];
[pauseStart release];
[previousFireDate release];
}
}

I used a UIButton and used this code when clicked.

remember to put this:

NSDate *pauseStart, *previousFireDate;

in your .h file

EDIT!

here is the countUp method. forget the down method. seconds, minutes, hours are Ints

- (void)countUp
{
seconds += 1;

if (seconds == 60)
{
seconds = 0;
minutes++;

if (minutes == 60)
{
minutes = 0;
hours++;
}
}

}


Related Topics



Leave a reply



Submit