skip to Main Content

Suppose I have a simple @Observable like

@Observable class Navigation {
    var path = NavigationPath()
}

And make an environment in my app structure like the migrating to observable docs recommend

@main
struct ObservableTestApp: App {
    @State private var navigation = Navigation()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(navigation)
        }
    }
}

I find that trying to use the @Environment from my view with NavigationStack like

struct ContentView: View {
    @Environment(Navigation.self) private var navigation

    var body: some View {
        NavigationStack(path: $navigation.path) {
            ...
        }
    }
}

Raises this compiler error

Cannot find ‘$navigation’ in scope

If we defined the @State on the ContentView instead, there is no compiler error.

Additionally, if I revert this to pre iOS 17 @ObservableObject using @StateObject and @EnvironmentObject (etc) then the compiler is fine with it. So it seems to be an issue with the new @Observable. Or perhaps my usage of it.

I understand there is an easy workaround but @ObservableObject behaving differently to @Observable is worth questioning.

2

Answers


  1. You need to use Bindable to get a bindable version of navigation.

    struct ContentView: View {
        @Environment(Navigation.self) private var navigation
    
        var body: some View {
            @Bindable var navigation = navigation
            NavigationStack(path: $navigation.path) {
                // ...
            }
        }
    }
    

    See the documentation, including this example:

    struct TitleEditView: View {
        @Environment(Book.self) private var book
    
    
        var body: some View {
            @Bindable var book = book
            TextField("Title", text: $book.title)
        }
    }
    
    Login or Signup to reply.
  2. pat/by.rmc/f
    Var.c/
    emphasized textjpug

    1. vrec"int

    question
    open minded
    2z0


    finish

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search