ObservableObject和Condition

时间:2020-02-27 11:20:39

标签: timer conditional-statements swiftui

我有一个计时器代码,该计时器自动启动,并应使用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()
    }
}



``

3 个答案:

答案 0 :(得分:0)

.onAppear {
    self.observed.start()
    if self.observed.waitingTimerCount == 3 {
        self.observed.stop()
    }
}

此代码如何工作?

它在视图出现时正在运行(很可能只有一次)

  1. 启动计时器
  2. 检查waitinigTimer == 3 //当前不是3
  3. 返回

所以,就像您已经知道的那样,它永远不会停止。

如果您要在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)

非常感谢。重置问题的解决方案可以在这里找到:

ObservableObject bug or not