如何在SwiftUI中即时更新View?
我有一个 Text
,它用作计时器,具有不同的数组值.并显示 timerIntervalSinceNow
.
I have a Text
that acts as a timer with different values of my array. And it displays with timerIntervalSinceNow
.
问题是当它达到零时,它应该显示为零,但是在再次单击屏幕之前不会发生.如果我不单击它,它会一直上升,因为它是 timeIntervalSinceNow
,但是当我单击它时,它会以 0秒
切换到 Text
.
The problem is when it reaches zero it should show zero to but that does not happen before clicking again on the screen. If I do not click on it it keeps going up since it is timeIntervalSinceNow
, but when I click it switches to the Text
with 0 sec
.
是否有任何方法告诉SwiftUI自行执行此操作而无需单击?
Any way on telling SwiftUI to do this by itself without clicking?
if(exerciseTime[value].timeIntervalSinceNow > 0) {
Text(exerciseTime[value], style:.relative).foregroundColor(.white).font(.largeTitle).padding(.top, 30)
} else {
Text("0 sec").foregroundColor(.white).font(.largeTitle).padding(.top, 30)
}
问题是 exerciseTime [value]
从不更改,因此视图不会重绘.
The issue is that exerciseTime[value]
never changes, so the view is not redrawn.
即使 exerciseTime [value] .timeIntervalSinceNow
可能有所不同,但实际的 exerciseTime [value]
仍保持不变.
Even though exerciseTime[value].timeIntervalSinceNow
might be different, the actual exerciseTime[value]
remains constant.
我建议您使用带有 ObservableObject
的 Timer
:
import Combine
import SwiftUI
class TimerViewModel: ObservableObject {
private var timer: AnyCancellable?
@Published var currentDate = Date()
func start(endDate: Date) {
timer = Timer.publish(every: 1.0, on: .main, in: .default)
.autoconnect()
.sink { [weak self] in
guard let self = self else { return }
self.currentDate = $0
if self.currentDate >= endDate {
self.timer = nil
}
}
}
}
并在您的视图中使用它:
and use it in your view:
struct TestView: View {
@State private var exerciseTime = Calendar.current.date(byAdding: .second, value: 15, to: Date())!
@StateObject private var timer = TimerViewModel()
var body: some View {
Group {
if timer.currentDate < exerciseTime {
Text(exerciseTime, style: .relative)
} else {
Text("0 sec")
}
}
.foregroundColor(.white)
.font(.largeTitle)
.padding(.top, 30)
.onAppear {
timer.start(endDate: exerciseTime)
}
}
}