我有一个计时器代码,该计时器自动启动,并应使用if语句再次停止。不幸的是,这行不通,并且我没有收到错误消息。我在这里做什么错了?
import SwiftUI
import Combine
import Foundation
class WaitingTimerClass: ObservableObject {
@Published var waitingTimerCount: Int = 0
var waitingTimer = Timer()
func start() {
self.waitingTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in self.waitingTimerCount += 1 } }
func stop() { waitingTimer.invalidate() }
func reset() { waitingTimerCount = 0; waitingTimer.invalidate() }
}
struct ContentView: View {
@ObservedObject var observed = WaitingTimerClass()
var body: some View {
Text("\(self.observed.waitingTimerCount)")
.onAppear {
self.observed.start()
if self.observed.waitingTimerCount == 3 {
self.observed.stop()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
``
答案 0 :(得分:0)
.onAppear {
self.observed.start()
if self.observed.waitingTimerCount == 3 {
self.observed.stop()
}
}
此代码如何工作?
它在视图出现时正在运行(很可能只有一次)
所以,就像您已经知道的那样,它永远不会停止。
如果您要在waitingTimer == 3时停止它,则必须在模型中执行。
@Published var waitingTimerCount: Int = 0 {
willSet {
if newValue == 3 { stop() }
}
}
答案 1 :(得分:0)
onAppear
块中的代码仅在View
出现时起作用一次(或多次,当视图消失并再次出现时)。在您的情况下,waitingTimerCount
始终为0。如果需要从视图中观察某些值,请使用onReceive
。代码应如下所示:
struct TimerWaiter: View {
@ObservedObject var observed = WaitingTimerClass()
var body: some View {
Text("\(self.observed.waitingTimerCount)")
.onAppear {
self.observed.start()
}
.onReceive(observed.$waitingTimerCount) { count in
guard count == 3 else { return }
self.observed.stop()
}
}
}
更新供第一作者评论:我不知道为什么重置计时器无法按预期工作,并且今天我没有多少时间。也许明天会更容易理解。这不是很好,但是可行的解决方案:
class WaitingTimerClass: ObservableObject {
@Published var waitingTimerCount: Int = 0
var didInvalidate = PassthroughSubject<Void, Never>()
var waitingTimer = Timer()
func start() {
self.waitingTimer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in self.waitingTimerCount += 1 } }
func stop() { waitingTimer.invalidate() }
func reset() {
waitingTimer.invalidate()
waitingTimerCount = 0
didInvalidate.send()
}
}
struct TimerWaiter: View {
@ObservedObject var observed = WaitingTimerClass()
@State private var count = 0
var body: some View {
Text("\(count)")
.onAppear {
self.observed.start()
}
.onReceive(observed.$waitingTimerCount) { count in
self.count = count
guard count == 3 else { return }
self.observed.reset()
}
.onReceive(observed.didInvalidate) { _ in
self.count = 0
}
}
}
建议。我将尝试更深入地了解为什么waitingTimerCount
的最后一次更改不会影响View
答案 2 :(得分:0)
非常感谢。重置问题的解决方案可以在这里找到: