Issue
This Content is from Stack Overflow. Question asked by Emere
I have been having problems with updating a published variable in my model, so I tried to replicate the problem with a very basic and simple set of files/codes. So basically in NavLink view
, there is a navigation link, which when clicked, it updates the published variable in ListRepository model
by giving it a string value of “yes”, prints it to the console then navigates to its destination which is called ContentView view
. The problem is in ContentView
, I tried to print the data contained in the published variable called selectedFolderId
hoping it will print “yes”, but i noticed that instead of printing the value that was set in NavLink view
, it instead printed the default value of ""
, which was not what was set in NavLink view
. Please can anyone explain the reason for this behaviour and explain to me how it can fix this as i am very new in swift ui. That will mean alot.
Please find the supporting files below:
import SwiftUI
struct NavLink: View {
@ObservedObject var listRepository = ListRepository()
var body: some View {
NavigationView{
ScrollView {
NavigationLink("Hello world", destination: ContentView())
Text("Player 1")
Text("Player 2")
Text("Player 3")
}
.simultaneousGesture(TapGesture().onEnded{
listRepository.selectedFolderId = "yes"
listRepository.md()
})
.navigationTitle("Players")
}
}
}
struct NavLink_Previews: PreviewProvider {
static var previews: some View {
NavLink()
}
}
import Foundation
class ListRepository: ObservableObject {
@Published var selectedFolderId = ""
func md(){
print("=====")
print(self.selectedFolderId)
print("======")
}
}
import SwiftUI
struct ContentView: View {
@ObservedObject var listRepository = ListRepository()
var body: some View {
VStack{
Text("content 1")
Text("content 2")
Text("content 3")
}
.onAppear{
print("========")
print(listRepository.selectedFolderId)
print("========")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Solution
This is a common issue when you first deal with data flow in an app. The problem is straightforward. In your ‘NavLink’ view you are creating one version of ListRepository
, and in ContentView
you create a separate and different version of ListRepository
. What you need to do is pass the ListRepository
created in NavLink
into ContentView
when you call it. Here is one example as to how:
struct NavLink: View {
@StateObject var listRepository = ListRepository() // Create as StateObject, not ObservedObject
var body: some View {
NavigationView{
ScrollView {
NavigationLink("Hello world", destination: ContentView(listRepository: listRepository)) // Pass it here
Text("Player 1")
Text("Player 2")
Text("Player 3")
}
.simultaneousGesture(TapGesture().onEnded{
listRepository.selectedFolderId = "yes"
listRepository.md()
})
.navigationTitle("Players")
}
}
}
struct ContentView: View {
@ObservedObject var listRepository: ListRepository // Do not create it here, just receive it
var body: some View {
VStack{
Text("content 1")
Text("content 2")
Text("content 3")
}
.onAppear{
print("========")
print(listRepository.selectedFolderId)
print("========")
}
}
}
You should also notice that I created ListRepository
as a StateObject
. The view that originally creates an ObservableObject
must create it as a StateObject
or you can get undesirable side effects.
This Question was asked in StackOverflow by Emere and Answered by Yrb It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.