Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

SwiftUI Observable environment compiler issue – cannot find in scope

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

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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.

>Solution :

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)
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading