Reputation: 91
Running on iOS 15. When I select a NavigationLink from ItemListView, the resultant ItemView animates onto the screen twice. I’ve discovered two (anti)fixes to this problem:
Don’t use nested NavigationLinks. If I treat ItemListView as the application’s primary view, bypassing NavigationTestView, and wrap the list in its own NavigationView, the views transition as expected. This is a non-starter because my application may require nesting of NavigationLinks.
Don’t use a navigation manager. Keeping the navigation state local to each view component and passing bindings around works as expected. This is maintenance nightmare however, and the code becomes unruly very quickly.
Is this a bug with SwiftUI and the underlying system, or am I making a mistake somewhere? If I’m making a mistake, what is it? If the problem is with SwiftUI what are some best practices to work around this issue until it is resolved?
Note that this code is adapted from code presented in this tutorial. Multiple people in the tutorial’s comments also complain of this very issue.
// NavigationManager.swift
class NavigationManager: ObservableObject {
@Published var itemListIsShown: Bool = false
@Published var selectedItem: String? = nil
}
// NavigationTestView.swift
// Application root view (Visually)
struct NavigationTestView: View {
@EnvironmentObject var navigationManager: NavigationManager
var body: some View {
NavigationView {
VStack {
Text("Primary view")
NavigationLink(
destination: ItemListView(),
isActive: $navigationManager.itemListIsShown) {
Text("Show item list")
}
}
}
}
}
// ItemListView.swift
struct ItemListView: View {
@EnvironmentObject var navigationManager: NavigationManager
let items: [String] = ["🍎", "🍓", "🍉", "🥭"]
var body: some View {
List(items, id: \.self) { item in
NavigationLink(
destination: ItemView(item: item),
tag: item,
selection: $navigationManager.selectedItem) {
Text(item)
}
}
.navigationTitle("Item list")
}
}
// ItemView.swift
struct ItemView: View {
@EnvironmentObject var navigationManager: NavigationManager
let item: String
var body: some View {
VStack(spacing: 30) {
Text(item)
Button {
navigationManager.selectedItem = nil
} label: {
Text("Deselect item")
}
}
}
}
Upvotes: 0
Views: 1020
Reputation: 856
works for me when I add .navigationViewStyle(.stack)
to the NavigationView
Upvotes: 4