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.
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)
}
}