My ObservedObject
will not connect with another view.
I have:
class AppState: ObservableObject {
@Published var destination: String = ""
@Published var arrivalTime = Date()
@Published var isLoading: Bool = false
@Published var cleanedTafString: String = ""
}
which declares the objects to be updated.
My main view, where I make the connection with my AppState()
class, once the button "GO" is pressed, the func LoadingProcess()
is executed which is inside of a Task
, runs an async
function runAllFunctions()
in a seperate swift file. Once That is complete, $readyToNavigate
(@State private var) triggers .navigationDestination
to change View
to ResultsScreenView()
:
struct InitialScreenView: View {
@ObservedObject private var app = AppState()
@State private var currentTimeDate = Date.now
@State private var readyToNavigate : Bool = false
var body: some View {
NavigationStack {
ZStack {
VStack {
VStack {
HStack {
Text(DateFormatterView.currentLocalDateFormatted())
}
.padding(2)
Text(DateFormatterView.currentGMTDateFormatted())
}
HStack {
TextFieldView(preFill: "Destination", fill: $app.destination)
}
Button(action: LoadingProcess, label: {
Text("GO")
})
.navigationDestination(isPresented: $readyToNavigate) {
ResultsScreenView()}
.navigationTitle("WxStrip")
}
if app.isLoading {
LoadingView()
}
}
}
}
func LoadingProcess() {
Task {
app.isLoading = true
let resultString = await app.runAllFunctions()
app.isLoading = false
// Update the observed object and trigger a refresh of the view
app.cleanedTafString = resultString
app.objectWillChange.send()
readyToNavigate = true
print(app.cleanedTafString)
}
}
}
Once the runAllFunctions()
function has finished inside the Task
, I am telling app.cleanedTafString
to update with the string that is returned from runAllFunctions()
.
This works fine for the current view if I wanted to display it in InitialScreenView
, but I don't. I need it on a separate View
called ResultsScreenView
.
struct ResultsScreenView: View {
@ObservedObject private var app = AppState()
var body: some View {
ZStack {
Button("Push me", action: {
DisplayCleaned()
})
}
}
func DisplayCleaned() {
print("Printout \(app.cleanedTafString)")
}
}
Ideally I want to display the string in a Text()
on screen but for troubleshooting have just called a function on press of the button....
This returns an empty string every time. It doesn't matter which of the @Published var
I try to print out, it just doesn't link somehow.
What is weird is that, on the initial declaration of the @Published var
if I enter some text instead of an empty string, it will print that instead of nothing. It's as though ResultsScreenView
is only ever looking at the initial declaration of the @Published var
and not seeing the updates. Although I know for sure they update as I can display it in print statements and in Text()
fields on screen in the InitialScreenView
....
As for working with
ObservableObject
, you must first declare your object with the@StateObject
property wrapper. It would initialize your object once and for all, and keep its state in memory even if the SwiftUI view refresh.Then, if you need to pass its state through child view, we will declare it as a
@ObservedObject
, but do not initialize it the way you did it inResultsScreenView
.You will have to pass your object through the
ResultsScreenView
initializer:As a reminder, it works the same way as
@State
and@Binding
, but for objects.