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.
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()
}
}
}
}