Pausing timer when app is in background state Swift
You have to set an observer listening to when the application did enter background. Add the below line in your ViewController's viewDidLoad() method.
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("myObserverMethod:"), name:UIApplicationDidEnterBackgroundNotification, object: nil)
Add the below function to receive the notification.
func myObserverMethod(notification : NSNotification) {
println("Observer method called")
//You may call your action method here, when the application did enter background.
//ie., self.pauseTimer() in your case.
}
Happy Coding !!!
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
}
}
}
Stop Time when lock phone in Background Mode
Luke has the right answer, I'm just going to add more detail. In your app delegate you can add
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
}
If you need to resume the timer on active you can use this method in your app delegate
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
For more info on stopping and starting timers, I recommend this link. Best of luck!
How can I pause and resume NSTimer.scheduledTimerWithTimeInterval in swift?
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
}
}
Related Topics
Ruby: Loaderror - Library Not Found for Class Digest::Sha1 -- Digest/Sha1
Xcode 9: Swift Dependency Analysis Error
How to Change How a Remote Notification Is Presented Before Presentation
Impelementation of Rtcdatachannel of Webrtc in iOS
Create Alert Function in All View Controllers - Swift
How to Add Two or More Buttons to Annotationview: Mkannotationview
Multiple Cells Selected on Scrolling [Reuse Cells Problem]
Get "No Keychain Available" Error When Try to Access Keychain from App Extension
Exc_Breakpoint (Sigtrap) on Production Version Only
Swift Language Multicast Delegate
How to Change a View from Portrait Mode to Landscape Mode and Lock It
Storyboard Localization in Swift 4.0
Required Initializers for a Subclass of Uiviewcontroller