SwiftUI:使用计时器时,每次平均执行会保持不变吗?
SwiftUI: When using a timer, will the average execution per time stay constant?
我目前正在开发一个内置计时器元素的应用程序。因此,如果用户选择 30 分钟,应用程序将显示剩余时间 -- 29:59、一秒后 29:58、29:57 等。计时器可以在几个小时内激活一个时间。经过一番研究,我发现有人说计时器不那么准确,不应该用于“高精度计时”?所以我不确定这会带来什么。计时器在一定时间内执行的平均速率在几个小时后是否仍保持不变?例如,如果我设置一个计时器每秒将一个整数加 1,那么在 4 小时后整数值是否为 14,400(前后大约 +/-10)(因为 4 小时内有 14,400 秒)?
import SwiftUI
struct ContentView: View {
@State var timeElapsed = 0
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack{
Text(String(timeElapsed)) //Would this display 14400 after 4 hours?
}
.onReceive(timer) { _ in
timeElapsed += 1
}
}
}
没有。没有保证每秒都会调用它。特别是,您的应用程序可能会进入后台,并且不会调用此计时器。 (超过 4 小时,这几乎是肯定的。)计时器不会累积未接来电。他们只是跳过它们。
实现计时器的方法是从当前时间减去开始时间,而不是尝试累加秒数。你想要更像这样的东西(未经测试):
struct ContentView: View {
@State var timeElapsed = 0
@State var startTime = Date()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack{
Text(String(timeElapsed)) //Would this display 14400 after 4 hours?
}
.onReceive(timer) { _ in
timeElapsed = Int(-startTime.timeIntervalSinceNow)
}
.onAppear { startTime = Date() }
}
}
还有一个iOS15的方法
import SwiftUI
@available(iOS 15.0, *)
struct NewTimerView: View {
let startDate: Date = Date()
var body: some View {
//A view that updates according to a schedule that you provide
TimelineView(.periodic(from: startDate, by: 1), content: {context in
Text((-startDate.timeIntervalSinceNow.rounded()).description)
})
}
}
https://developer.apple.com/documentation/swiftui/timelineview
来自 WWDC 的锻炼应用程序代码对其进行了跟踪
https://developer.apple.com/wwdc21/10009
我目前正在开发一个内置计时器元素的应用程序。因此,如果用户选择 30 分钟,应用程序将显示剩余时间 -- 29:59、一秒后 29:58、29:57 等。计时器可以在几个小时内激活一个时间。经过一番研究,我发现有人说计时器不那么准确,不应该用于“高精度计时”?所以我不确定这会带来什么。计时器在一定时间内执行的平均速率在几个小时后是否仍保持不变?例如,如果我设置一个计时器每秒将一个整数加 1,那么在 4 小时后整数值是否为 14,400(前后大约 +/-10)(因为 4 小时内有 14,400 秒)?
import SwiftUI
struct ContentView: View {
@State var timeElapsed = 0
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack{
Text(String(timeElapsed)) //Would this display 14400 after 4 hours?
}
.onReceive(timer) { _ in
timeElapsed += 1
}
}
}
没有。没有保证每秒都会调用它。特别是,您的应用程序可能会进入后台,并且不会调用此计时器。 (超过 4 小时,这几乎是肯定的。)计时器不会累积未接来电。他们只是跳过它们。
实现计时器的方法是从当前时间减去开始时间,而不是尝试累加秒数。你想要更像这样的东西(未经测试):
struct ContentView: View {
@State var timeElapsed = 0
@State var startTime = Date()
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack{
Text(String(timeElapsed)) //Would this display 14400 after 4 hours?
}
.onReceive(timer) { _ in
timeElapsed = Int(-startTime.timeIntervalSinceNow)
}
.onAppear { startTime = Date() }
}
}
还有一个iOS15的方法
import SwiftUI
@available(iOS 15.0, *)
struct NewTimerView: View {
let startDate: Date = Date()
var body: some View {
//A view that updates according to a schedule that you provide
TimelineView(.periodic(from: startDate, by: 1), content: {context in
Text((-startDate.timeIntervalSinceNow.rounded()).description)
})
}
}
https://developer.apple.com/documentation/swiftui/timelineview
来自 WWDC 的锻炼应用程序代码对其进行了跟踪 https://developer.apple.com/wwdc21/10009