ObservableObject and Condition - PullRequest
       7

ObservableObject and Condition

0 голосов
/ 27 февраля 2020

У меня есть код для таймера, который запускается автоматически и должен снова остановиться с оператором 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 голосов
/ 27 февраля 2020

Код в блоке 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
        }
    }

}

PS Я попытаюсь покопаться глубже, чтобы понять, почему последнее изменение waitingTimerCount не влияет на View

0 голосов
/ 01 марта 2020

Большое спасибо. решение проблемы сброса можно найти здесь:

Ошибка ObservableObject или нет

0 голосов
/ 27 февраля 2020
.onAppear {
    self.observed.start()
    if self.observed.waitingTimerCount == 3 {
        self.observed.stop()
    }
}

Как работает этот код?

он работает, когда появляется представление (скорее всего, только один раз)

  1. запустить таймер
  2. проверено, если waitinigTimer == 3 // это не 3 в данный момент
  3. return

Итак, он просто никогда не останавливается, как вы уже знаете.

Если вам нравится чтобы остановить его, если waitTimer == 3, вы должны сделать это в своей модели.

@Published var waitingTimerCount: Int = 0 {
    willSet {
        if newValue == 3 { stop() }
    }    
}
...