我的应用程序的核心部分是一个计时器。到目前为止,这是代码(从主代码库中取出,以尽量减少可重现性):
import SwiftUI
struct TestView: View {
@State var countdownTimer = 5 * 60 /// The actual seconds of the timer, being counted down/up
@State var timerRunning = false /// Var to set and see if timer is running
var body: some View {
/// For formatting the timer numbers
let style = Duration.TimeFormatStyle(pattern: .minuteSecond)
let formTimer = Duration.seconds(countdownTimer).formatted()
let formTimerShort = Duration.seconds(countdownTimer).formatted(style)
/// The main Timer If there are no hours we hide the hour number and make the timer bigger in this way.
Text(countdownTimer / 3600 == 0 && timerRunning ? "\(formTimerShort)" : "\(formTimer)")
.onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect()) { _ in
if countdownTimer > 0 && timerRunning {
countdownTimer -= 1
} else {
timerRunning = false
}
}
/// The Start and Pause buttons
HStack {
if !timerRunning {
Button(action: {
timerRunning = true
}) {
Text("Start")
.frame(width: 300, height: 75)
.font(.system(size: 60))
}
} else {
Button(action: {
timerRunning = false
}) {
Text("Pause")
.frame(width: 300, height: 75)
.font(.system(size: 60))
}
}
}
}
}
#Preview {
TestView()
}
问题在于它不准确。1 小时的计时器使用时间大约为 40 秒。所以我的想法是将计时器的发布时间从 1 改为 0.001,从而提高分辨率。此代码有效,但准确性更低!
struct TestView: View {
@State var countdownTimer = 5 * 60 /// The actual seconds of the timer, being counted down/up
@State private var fractionTimer = 0 /// Helping us to make the timer more accurate
@State var timerRunning = false /// Var to set and see if timer is running
var body: some View {
[...]
/// The main Timer If there are no hours we hide the hour number and make the timer bigger in this way.
Text(countdownTimer / 3600 == 0 && timerRunning ? "\(formTimerShort)" : "\(formTimer)")
.onReceive(Timer.publish(every: 0.001, on: .main, in: .common).autoconnect()) { _ in
/// Count up the fraction timer, only if he hits a certain Number we count up our Visible Timer
if timerRunning {
fractionTimer += 1
}
if fractionTimer == 1000 {
if countdownTimer > 0 && timerRunning {
countdownTimer -= 1
fractionTimer = 0
} else {
timerRunning = false
fractionTimer = 0
}
}
}
[...]
}
}
根据我的逻辑,这应该将误差从每小时 40 秒降低到每小时 0.04 秒。但实际上现在误差是每小时 120 秒!
怎么会这样?是不是因为它在主线程上运行,并且每秒调用 1000 次,所以有许多其他任务会延迟该调用?我应该从主线程中获取它吗?