【问题标题】:ObservableObject and ConditionObservableObject 和 Condition
【发布时间】:2020-02-27 11:20:39
【问题描述】:

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



``

【问题讨论】:

    标签: timer conditional-statements swiftui


    【解决方案1】:

    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
            }
        }
    
    }
    

    P.S.我会尝试更深入地了解,为什么waitingTimerCount的最后一次更改不会影响视图

    【讨论】:

    • 有效。我明白了。谢谢你。但是为什么它不能与reset()一起工作呢?计数器停止但未设置为 0。
    • @cris 现在我想不通,为什么reset() func 不能按预期工作。明天我会试着理解它,也许吧。我添加了一些修补程序,也许会有所帮助
    • 我很好奇。谢谢
    【解决方案2】:
    .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() }
        }    
    }
    

    【讨论】:

      【解决方案3】:

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

      ObservableObject bug or not

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-11-18
        • 1970-01-01
        • 2017-05-25
        • 2016-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多