I was thinking about using DataFormatter.localizedString... and setting the value to 2 different variables, one for when the app leaves the foreground and when the app comes back to the foreground, and then subtracting them to get the elapsed time to set it to the breakSession.text...but I'm a little new to swift and am unclear how to use the Date() functions. My main goal is to have it so that the breakTimer is running when the app is in the background and pauses when it is in the foreground, but the user should still be able to see the elapsed time. But apparently, timers can't run in the background...Can anyone help?
import UIKit
class HomeViewController: UIViewController {
@IBOutlet weak var focusSession: UILabel!
@IBOutlet weak var breakSession: UILabel!
/** Focus Time **/
var prodMinutes = String() // Productive time data from ViewController.swift arrives and is stored
lazy var intProdSeconds = (60*Int(prodMinutes)!) + 1
var focusTimer = Timer()
var isFocusTimerRunning = false // Make sure only one timer is running at a time
/** Break Time **/
var breakMinutes = String() // Break time data from BreaTimeViewController.swift arrives and is stored
lazy var intBrSeconds = (60*Int(breakMinutes)!) + 1
var breakTimer = Timer()
var isBreakTimerRunning = false
override func viewDidLoad() {
super.viewDidLoad()
let state: UIApplicationState = UIApplication.shared.applicationState
/** Focus Time **/
if isFocusTimerRunning == false && state == .active {
runProdTimer()
}
else {
focusTimer.invalidate()
}
/** Break Time (This part doesn't work)
if isBreakTimerRunning == false && state == .background {
runBrTimer()
}
else {
breakTimer.invalidate()
} **/
}
func runProdTimer() {
focusTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(HomeViewController.updateProdTimer)), userInfo: nil, repeats: true)
isFocusTimerRunning = true
}
func runBrTimer() {
breakTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: (#selector(HomeViewController.updateBrTimer)), userInfo: nil, repeats: true)
isBreakTimerRunning = true
}
@objc func updateProdTimer() {
if intProdSeconds < 1 {
focusTimer.invalidate()
focusSession.text = "00:00"
}
else {
intProdSeconds -= 1
focusSession.text = prodTimeString(fTime: TimeInterval(intProdSeconds))
}
}
@objc func updateBrTimer() {
if intBrSeconds < 1 {
breakTimer.invalidate()
breakSession.text = "00:00"
}
else {
intBrSeconds -= 1
breakSession.text = brTimeString(bTime: TimeInterval(intBrSeconds))
}
}
func prodTimeString(fTime: TimeInterval) -> String {
let prodMinutes = Int(fTime) / 60 % 60
let prodSeconds = Int(fTime) % 60
return String(format: "%02d:%02d", prodMinutes, prodSeconds)
}
func brTimeString(bTime: TimeInterval) -> String {
let brMinutes = Int(bTime) / 60 % 60
let brSeconds = Int(bTime) % 60
return String(format: "%02d:%02d", brMinutes, brSeconds)
}
Update: Ok so Sunil Chauhan's answer below sort of worked. I am able to get the time stamp and stuff. However, I ran into another problem and I do not understand why..
@objc func appWillEnterForeground() {
endDate = Date()
let secondsPassedInBackground = endDate.timeIntervalSince(beginDate)
print(secondsPassedInBackground)
let updateBrTime = intBrSeconds - Int(secondsPassedInBackground) // Updated Break Time after user returns to the app aka foreground
breakSession.text = brTimeString(bTime: TimeInterval(updateBrTime))
}
In this function, I basically want to take the elapsed time and subtract it from intBrSeconds which is like the "Break" time the user sets for themself. So essentially, this works as a timer as the "Break Timer" runs when the user leaves the app. The label updates properly at first and correctly subtracts the right amount of seconds based on how much time has elapsed. However, after the elapsed time exceeds about 30 seconds or so, the timer starts to increase. So like if it was set to 10:00..it will go down to say, 9:34 but then the next time you leave the app in the background and come back, it will say 9:55 or something greater than 9:34 which is not supposed to happen..how can I fix this?