Reputation: 57
I am writing a stopwatch application for timekeeping and I need to check if the clock is over a certain time interval (like 20:00 - 06:00) and in that case add the current elapsed time to a TimeInterval variable that I later will store in a database. Any ideas on how I can achieve this? So far I've tried to check it in the tick function but then it doesn't add the time when the app is in the background.
import Foundation
import os.log
/// The class protocol for a Stopwatch instance.
protocol StopwatchDelegate: class {
func currentTimerUpdated(seconds: String, minutes: String, hours: String)
func timerHasStarted()
func timerHasStopped()
func timerWasReset()
}
/// A container for a stopwatch.
class Stopwatch{
//var currentTimerSession = [TimerSession] = []
// *****************************************************************
// MARK: - Stopwatch Properties
// *****************************************************************
/// The middleman for communicating with the view controller.
weak var delegate: StopwatchDelegate?
/// The actual Timer for this stopwatch.
private(set) var timer: Timer?
/// The time at which the timer was started.
private(set) var timerStartTime: TimeInterval = 0
/// The Timer-time at which the last user *pause* occurred.
private(set) var timerSavedTime: TimeInterval = 0
private(set) var timerSession = false
// *****************************************************************
// MARK: - Stopwatch Class Methods
// *****************************************************************
/// Create a new Stopwatch by locating the middleman and starting the timer.
///
/// - Parameter delegate: the middleman to communicate to the view controller.
/// - Returns: An instance to a ticking `Stopwatch`.
///
init(delegate: StopwatchDelegate) {
os_log("Initilzing timer.", log: OSLog.default, type: .debug)
self.delegate = delegate
}
// *****************************************************************
// MARK: - Stopwatch Timer Methods
// ***************************************************************** *****************************************************************
/// Start the stopwatch's timer.
func startTimer() {
timer = Timer.scheduledTimer(timeInterval: 0.01, target: self,
selector: #selector(timerHasTicked(timer:)),
userInfo: nil, repeats: true)
RunLoop.current.add(timer!, forMode: RunLoopMode.commonModes)
/// Record the time at which we started this timer.
//checkForOngoingTimer()
timerStartTime = Date.timeIntervalSinceReferenceDate
timerOriginalStartTime = Date()
timerSession = true
delegate?.timerHasStarted()
}
/// Pause the Timer
func stopTimer() {
/// Save the Time delta of the current Timer.
let currentTime = Date.timeIntervalSinceReferenceDate
timerSavedTime += currentTime - timerStartTime
timer?.invalidate()
delegate?.timerHasStopped()
}
/// Reset the Timer and all of the laps.
func resetTimer() {
timerSavedTime = 0
timerStartTime = 0
timerSession = false
timer?.invalidate()
delegate?.timerWasReset()
}
/// Compute the new time values time values:
///
/// - `minutes`: starts at 0 and increments to 59
/// - `seconds`: starts at 0 and increments to 59
/// - `hours`: starts at 0 and increments to 59
///
/// - Parameter timer: The instance of the currently *running* Timer.
///
@objc private func timerHasTicked(timer: Timer) {
/// Find the time delta between start time and now.
let currentTime = Date.timeIntervalSinceReferenceDate
let timerElapsedTime: TimeInterval = (currentTime - timerStartTime) + timerSavedTime
/// Convert elapsed time to minutes, seconds, and hours.
let minutes = Int(timerElapsedTime) / 60 % 60
let seconds = Int(timerElapsedTime) % 60
let hours = Int(timerElapsedTime / 3600)
let formatter = DateFormatter()
formatter.timeZone = TimeZone.current
formatter.dateFormat = "yyyy-MM-dd HH:mm"
timerOriginalStartTime = formatter.string(from: timerOriginalStartTime)
/// Let the delegate know the Time has been updated.
delegate?.currentTimerUpdated(seconds: String(format: "%02u", seconds),
minutes: String(format: "%02u", minutes),
hours: String(format: "%02u", hours))
}
}
Upvotes: 0
Views: 944
Reputation: 6579
Your timer won't get fired in the background, so the best way to go is is to store the start time when you start the stopwatch, then when the app goes to the background and comes back again, you can calculate the current offset from the starttime.
If you want to support pauzing the timer, you could keep track of start and stop times of the pause and subtract that from the total time.
Upvotes: 2