Swiftui timer not firing after navigating back

大兔子大兔子 提交于 2021-02-11 07:02:39

问题


i have a timer in SwiftUI which works when opening the view for the first time. When navigating back and opening again, the timer does not start. Any idea what can be wrong ?

import SwiftUI

struct ClockDetail: View {

    @State var seconds: Int = 0
    @ObservedObject var motion: MotionManager
    let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        VStack(alignment: .leading) {
            Text("\(seconds)").font(.title).onReceive(timer) { output in
                self.seconds += 1
            }
            Text("Attitude Data").foregroundColor(.blue)
            Text("Roll: \(motion.roll)")
            Text("Pitch: \(motion.pitch)")
            Text("Yaw: \(motion.yaw)")
        }.onDisappear(perform: {
            self.timer.upstream.connect().cancel()
        })
    }
}


struct ClockDetail_Previews: PreviewProvider {
    static var previews: some View {
        ClockDetail(motion: MotionManager())
    }
}

I'm using the .onDisappear to cancel the timer but seems that doesn't do the job.


回答1:


Your ClockDetail is created only once, so once you invalidate timer it does not work anymore when you navigate again, because view is the same, but already w/o timer.

With the introduction of view model, as in below demo approach, it is better manageable I assume.

Tested with Xcode 11.2 / iOS 13.2. Note, I commented dependencies on not available entities, as they are not important for considered issue.

class ClockDetailViewModel: ObservableObject {
    @Published var seconds = 0
    private var subscriber: AnyCancellable?

    func setup() {
        self.seconds = 0
        self.subscriber = Timer
            .publish(every: 1, on: .main, in: .common)
            .autoconnect()
            .sink(receiveValue: { _ in
                self.seconds += 1
            })
    }

    func cleanup() {
        self.subscriber = nil
    }
}

struct ClockDetail: View {

    @State private var seconds: Int = 0
//    @ObservedObject var motion: MotionManager
    @ObservedObject private var vm = ClockDetailViewModel()

    var body: some View {
        VStack(alignment: .leading) {
            Text("\(vm.seconds)").font(.title)
            Text("Attitude Data").foregroundColor(.blue)
//            Text("Roll: \(motion.roll)")
//            Text("Pitch: \(motion.pitch)")
//            Text("Yaw: \(motion.yaw)")
            .onAppear {
                self.vm.setup()
            }
            .onDisappear {
                self.vm.cleanup()
            }
        }
    }
}


来源:https://stackoverflow.com/questions/60588413/swiftui-timer-not-firing-after-navigating-back

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!