Hi,
I am having trouble changing from deprecated NavigationView to NavigationStack.
I have looked through the article, and a number of examples and tutorials - they all show examples where the user clicks on a choice or a button in the view. But in my case, the navigation is programmatic based on changes to a value. I have below the old code, and my attempt at new revised code ( needs to run on IOS16, and cannot use API introduced in IOS 17). The new code compiles fine, but the screen does not navigate to new views as the value changes. I debug print the value as it changes, and the value for 'detailView' does change. The old code works without a problem - just that I get a warning that I am using deprecated APIs.
The old code:
struct MainView: View {
@EnvironmentObject var gameVm: GameViewModel
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: PlayView().transition(.slide),
tag: .playView, selection: $gameVm.detailView) {
EmptyView()
}
NavigationLink(destination: GamePausedView().transition(.scale),
tag: .gamePausedView, selection: $gameVm.detailView) {
EmptyView()
}
NavigationLink(destination: SettingsView().transition(.slide),
tag: .settingsView, selection: $gameVm.detailView) {
EmptyView()
}
IdleView().transition(.slide)
}
}
.navigationViewStyle(.stack)
}
}
My attempt at the revised code:
struct GameMainView: View {
@EnvironmentObject var gameVm: GameViewModel
@State private var path = NavigationPath()
var body: some View {
NavigationStack(path: $path) {
VStack {
NavigationLink(value: DetailView.playView) {
EmptyView()
}
NavigationLink(value: DetailView.gamePausedView) {
EmptyView()
}
NavigationLink(value: DetailView.settingsView) {
EmptyView()
}
IdleView().transition(.slide)
}
}
.navigationDestination(for: DetailView.self) { dtlViewType in
if dtlViewType == .playView {
PlayView().transition(.slide)
} else if dtlViewType == .settingsView {
SettingsView().transition(.slide)
} else if dtlViewType == .gamePausedView {
GamePausedView().transition(.slide)
}
}
}
}
What am I doing wrong? Thanks in advance for any help.
The navigationDestination(for:destination:)
modifier need to be applied inside the NavigationStack
. For example:
enum DetailView: Hashable {
case playView
case gamePausedView
case settingsView
}
struct ContentView: View {
var body: some View {
NavigationStack {
VStack {
NavigationLink(value: DetailView.playView) {
Text("Play")
}
NavigationLink(value: DetailView.settingsView) {
Text("Settings")
}
NavigationLink(value: DetailView.gamePausedView) {
Text("Pause")
}
}
.navigationDestination(for: DetailView.self) { selection in
switch selection {
case .gamePausedView:
Text("Game paused view")
case .playView:
Text("Play view")
case .settingsView:
Text("Settings view")
}
}
}
}
}