I have a @Published Date() variable that I want to update every 5 seconds to keep app time in sync.\
I tired placing the timer inside the class, but that does not revolve the issue either.
video preview videolink (YouTube)
import SwiftUI
struct ContentView: View {
@State var countdown = Timer.publish(every: 2, on: .current, in: .default).autoconnect()
@ObservedObject var timer = globalTime()
var body: some View {
VStack{
Text("time \(timer.currentDate)")
Text("This is a view")
}
.toolbar(content: {
ToolbarItem(id: "help",placement: .navigationBarLeading) {
NavigationLink(
destination: ContentView2(),
label: {
Text("View Link")
})
}
})
.onReceive(countdown, perform: { _ in
timer.currentDate = timer.currentDate.addingTimeInterval(2)
})
}
}
class globalTime: ObservableObject {
@Published var currentDate = Date(timeIntervalSince1970: 12)
}
//NavigationLink View
struct ContentView2: View {
@ObservedObject var global = globalTime()
var body: some View {
VStack{
Text("This is a view")
}
}
}
CodePudding user response:
For starters, you have a Publisher
stored as a @State
variable, which you shouldn't be doing. That timer is never modified and should be a let
property, or bound to a Published
variable, on your ObservableObject
. Second, in ContentView2
you have an observable object being set from inside the same view but ObservableObject
means that that object's storage is handled externally, so by assigning the value where it's declared, you're violating the observable object contract. If you want to declare it inside your view, use @StateObject
; ObservableObject
is used when you pass view models down to children views. In that case, the parent is responsible for the view models storage so that when the child reloads, it doesn't also reload the view model.
I ran your code and I am not getting multiple navigation link pushes like your video shows. If you're still experiencing the issue, try a couple things:
- define your timer publisher on the observable object
- change
@ObservableObject
to@StateObject
CodePudding user response:
there are a number of issues with your code. You need a NavigationView
to be
able to use a NavigationLink
. Also you need to pass the timer
to your next View
ContentView2
for it to be available in that view. The following code shows some
of these concepts.
struct ContentView: View {
let countdown = Timer.publish(every: 2, on: .current, in: .default).autoconnect()
@StateObject var timer = globalTime() // <-- here
var body: some View {
NavigationView {
VStack{
Text("time \(timer.currentDate)")
}
.toolbar {
ToolbarItem(id: "help", placement: .navigationBarLeading) {
NavigationLink(destination: ContentView2(global: timer)) {
Text("View Link")
}
}
}
.onReceive(countdown) { _ in
timer.currentDate = timer.currentDate.addingTimeInterval(2)
}
}
}
}
class globalTime: ObservableObject {
@Published var currentDate = Date(timeIntervalSince1970: 12)
}
struct ContentView2: View {
@ObservedObject var global: globalTime // <-- here
var body: some View {
VStack{
Text("This is a view")
Text("time \(global.currentDate)") // <-- here
}
}
}