Я хочу иметь секундомер в своем приложении, который полностью работает со временем устройства. У меня есть мой код ниже, который принимает время, в течение которого нажата кнопка запуска, а затем каждую секунду обновляет secondsElapsed
, чтобы быть разницей между startTime
и текущим. Я застреваю в реализации функции паузы. Если я просто аннулирую таймер обновления, то таймер перезапустится, в значительной степени продолжая с того места, где он остановился. Любые идеи о том, как это можно сделать?
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()
}
}
Я показываю секундомер, используя этот код ниже:
struct ContentView: View {
@ObservedObject var stopWatchManager = StopWatchManager()
var body: some View{
HStack{
Button("Start"){
stopWatchManager.startWatch()
}
Text("\(stopWatchManager.secondsElapsed)")
Button("Pause"){
stopWatchManager.pauseWatch()
}
}
}
}
Да. Вот как это сделать:
startTime
и перезапустите таймер обновления.Вот обновленный код:
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
}
}
Что следует отметить:
0.1
на 1
, чтобы не пропускать обновления.paused
и running
, чтобы кнопки не нажимались более одного раза подряд.Да, возьмите время при нажатии кнопки возобновления и вычтите прошедшее время, чтобы получить новое startTime
. У меня есть код, чтобы добавить к моему ответу. Прежде чем я добавлю его, какой кнопкой вы хотите возобновить таймер, Start
или Pause
? Или, возможно, Pause
следует изменить на Unpause
или Resume
, когда время поставлено на паузу.
В моем полном приложении кнопка меняется с «Начать просмотр» на «Пауза просмотра» (при нажатии), а затем обратно, чтобы начать просмотр. Поэтому я хотел бы начать, чтобы возобновить его
let diffComponents = Calendar.current.dateComponents([.second], from: self.startTime, to: current)
?? почему бы и не Date().timeIntervalSince(startTime)
или startTime.timeIntervalSinceNow
тоже?
Date().addingTimeInterval(-elapsedTime)
также может быть записано как Date(timeIntervalSinceNow: -elapsedTime)
или просто Date() - elapsedTime
Под возобновлением таймера вы имеете в виду время в момент нажатия, а затем вычитание прошедшего времени? Я думаю, что меня путают с моими именами переменных и вашей формулировкой. Спасибо за помощь!