@Publish 计数器在定时器 SwiftUI 中不同步
@Publish counters not in sync inside timer SwiftUI
我正在开发一个应用程序,在该应用程序中,我使用计时器对锻炼中剩余的时间进行倒计时,并计算总时间。我的计数器不同步,看起来不到一秒。我想知道它是否与@Publish 有关,也许一个先于另一个触发。知道发生了什么以及如何解决它吗?
class TimeManager: ObservableObject {
@Published var totalTime: Double = 0.0
@Published var timeRemaining: Double = 180.0
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0) {
self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] timer in
guard let self = self else { return }
self.timeRemaining -= 0.1
self.totalTime += 0.1
}
}
}
然后是我的看法
@ObservedObject var timeManager = TimeManager()
...
var body: some View {
VStack {
let time = timeManager.timeRemaining
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
ZStack {
Progress()
Text(String(format:"%02i:%02i", minutes, seconds))
.font(.system(size: 60))
}
let total = timeManager.totalTime
let totalMins = Int(total) / 60 % 60
let totalSecs = Int(total) % 60
Text(String(format:"%02i:%02i", totalMins, totalSecs))
.font(.system(size: 40))
}
}
当你减少时间时,也许可以根据第一个值计算你的第二个值。例如像这样:
剩余 = (180 - 总计) >= 0 ? (180 - 总计):0
您的时间值已同步。您看到的行为的原因是 Double
/ Int
转换和显示 Text
时应用的舍入。试试这一行:
Text("\(timeManager.timeRemaining + timeManager.totalTime)")
你会发现这总和是 180。
您可以尝试将 Viewmodel 中的 Int 值 decrementing/incrementing 乘以 1 和 DateComponentsFormatter
来格式化视图中的值。
let componentsFormatter = DateComponentsFormatter()
Text("\(componentsFormatter.string(from: Double(timeManager.timeRemaining)) ?? "NAN")")
.font(.system(size: 60))
您当然需要调整格式化程序以按照您希望的方式显示时间。但我同意 Paulw11。这似乎是一个糟糕的设计。最好有一个单一的真实来源作为 Date
然后从那里开始。
我正在开发一个应用程序,在该应用程序中,我使用计时器对锻炼中剩余的时间进行倒计时,并计算总时间。我的计数器不同步,看起来不到一秒。我想知道它是否与@Publish 有关,也许一个先于另一个触发。知道发生了什么以及如何解决它吗?
class TimeManager: ObservableObject {
@Published var totalTime: Double = 0.0
@Published var timeRemaining: Double = 180.0
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0) {
self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] timer in
guard let self = self else { return }
self.timeRemaining -= 0.1
self.totalTime += 0.1
}
}
}
然后是我的看法
@ObservedObject var timeManager = TimeManager()
...
var body: some View {
VStack {
let time = timeManager.timeRemaining
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
ZStack {
Progress()
Text(String(format:"%02i:%02i", minutes, seconds))
.font(.system(size: 60))
}
let total = timeManager.totalTime
let totalMins = Int(total) / 60 % 60
let totalSecs = Int(total) % 60
Text(String(format:"%02i:%02i", totalMins, totalSecs))
.font(.system(size: 40))
}
}
当你减少时间时,也许可以根据第一个值计算你的第二个值。例如像这样: 剩余 = (180 - 总计) >= 0 ? (180 - 总计):0
您的时间值已同步。您看到的行为的原因是 Double
/ Int
转换和显示 Text
时应用的舍入。试试这一行:
Text("\(timeManager.timeRemaining + timeManager.totalTime)")
你会发现这总和是 180。
您可以尝试将 Viewmodel 中的 Int 值 decrementing/incrementing 乘以 1 和 DateComponentsFormatter
来格式化视图中的值。
let componentsFormatter = DateComponentsFormatter()
Text("\(componentsFormatter.string(from: Double(timeManager.timeRemaining)) ?? "NAN")")
.font(.system(size: 60))
您当然需要调整格式化程序以按照您希望的方式显示时间。但我同意 Paulw11。这似乎是一个糟糕的设计。最好有一个单一的真实来源作为 Date
然后从那里开始。