0

I am trying to pass data from one View to another using @StateObject navigating using NavigationStack and NavigationPath. In my case I can't use NavigationLink.

enter image description here

To achieve that a came up with this code:

    struct ContentView: View {
    @State private var inputValue: String = ""
    @StateObject private var dataStore = DataStore()
    @StateObject var coordinator = Coordinator()
    
    var body: some View {
        NavigationStack(path: $coordinator.path) {
            VStack {
                TextField("Enter a value", text: $inputValue)
                    .padding()
                
                Button("Next") {
                    dataStore.stringValue = inputValue
                    coordinator.gotoNext()
                }
                .padding()

            }
            .navigationDestination(for: Destination.self) { destination in
                switch destination {
                case .ContentView:
                    ContentView()
                case .NextView:
                    NextView()
                }
            }
            .environmentObject(coordinator)
        }
    }
}

The first View

struct NextView: View {
    @StateObject private var dataStore = DataStore()
    @EnvironmentObject var coordinator: Coordinator
    var body: some View {
            VStack {
                Text("Value from previous view:")
                    .padding()
                Text(dataStore.stringValue)
                    .padding()
                Button {
                    coordinator.gotoHomePage()
                } label: {
                    Text("Back to home page")
                }
            }
        
    }
}

The second View

class Coordinator: ObservableObject {
    @Published var path = NavigationPath()
    
    func gotoHomePage() {
        print("Go to Home")
        path.removeLast(path.count)
    }
    
    func gotoNext() {
        print("gotoNext")
        path.append(Destination.NextView)
    }
    
    func goBack() {
        print("goBack")
        path.removeLast()
    }
}

The Coordinator (NavigationPath)

class DataStore: ObservableObject {
    @Published var stringValue: String = ""
}

enum Destination {
    case ContentView
    case NextView
}

Data Structure and navigation

When I run the code, I can navigate forward (to the NextView, but no values appears and when I try to get back to the ContentView, the code crashs.

Looks like there aren't data in de enviroment neither DataStore are holding value.

What I'm doing wrong?

** Update 1

When I move the environment set to the App struct then the code works fine:

import SwiftUI

@main
struct NavigationStackApp: App {
    @StateObject var dataStore = DataStore()
    @StateObject var coordinator = Coordinator()
    private var root = ContentView()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(coordinator)
                .environmentObject(dataStore)
        }
    }
}

** Update 2

So If I want to do this from a view struct instead of App struct I should create an mainView to set the environment and encapsulate the first view that will use the environment objects:

struct MainView:View {
    @StateObject var dataStore = DataStore()
    @StateObject var coordinator = Coordinator()
    var body: some View {
        ContentView()
            .environmentObject(coordinator)
            .environmentObject(dataStore)
    }
}
Sebastian
  • 6,154
  • 5
  • 33
  • 51
  • The data stores have no connection to each other – lorem ipsum May 20 '23 at 21:05
  • You should not have `@StateObject private var dataStore = DataStore()` in your `NextView` and `ContentView` etc... use `@EnvironmentObject var dataStore: DataStore` in those views. You should have only **one** `@StateObject private var dataStore = DataStore()` (in your `NavigationStackApp`) that you pass around using the `.environmentObject(dataStore)`. – workingdog support Ukraine May 21 '23 at 01:04

0 Answers0