Reputation: 417
I am wanting to have a stopwatch in my app that runs completely off the device's time. I have my code below which takes the time in which the start button is pressed, and then every second updates the secondsElapsed
to be the difference between the startTime
and current. I am getting stuck on implementing a pause function. If I just invalidate the update timer, then the timer will restart having pretty much carried on from where it left off. Any ideas on how this could be done?
class StopWatchManager: ObservableObject{
@Published var secondsElapsed = 0
var startTime: Date = Date()
var timer = Timer()
func startWatch(){
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true){ timer in
let current = Date()
let diffComponents = Calendar.current.dateComponents([.second], from: self.startTime, to: current)
let seconds = (diffComponents.second ?? 0)
self.secondsElapsed = seconds
}
}
func pauseWatch(){
timer.invalidate()
}
}
I display the stopwatch using this code below:
struct ContentView: View {
@ObservedObject var stopWatchManager = StopWatchManager()
var body: some View{
HStack{
Button("Start"){
stopWatchManager.startWatch()
}
Text("\(stopWatchManager.secondsElapsed)")
Button("Pause"){
stopWatchManager.pauseWatch()
}
}
}
}
Upvotes: 0
Views: 396
Reputation: 154533
Yes. Here is how to do it:
startTime
and restart the update timer.Here's the updated code:
class StopWatchManager: ObservableObject{
@Published var secondsElapsed = 0
var startTime: Date = Date()
var elapsedTime = 0.0
var paused = false
var running = false
var timer = Timer()
func startWatch(){
guard !running else { return }
if paused {
startTime = Date().addingTimeInterval(-elapsedTime)
} else {
startTime = Date()
}
paused = false
running = true
timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true){ timer in
let current = Date()
let diffComponents = Calendar.current.dateComponents([.second], from: self.startTime, to: current)
let seconds = (diffComponents.second ?? 0)
self.secondsElapsed = seconds
}
}
func pauseWatch(){
guard !paused else { return }
timer.invalidate()
elapsedTime = Date().timeIntervalSince(startTime)
paused = true
running = false
}
}
Things to note:
0.1
from 1
to avoid missing updates.paused
and running
state variables to keep the buttons from being pressed more than once in a row.Upvotes: 2