I'm building an iOS app with SwiftUI and am encountering unexpected behaviour when navigating from a List
view to a detail view.
I have three views: ViewA
, ViewB
, and ViewC
. ViewA
navigates to ViewB
, which is a list of Item
instances. Tapping on an Item
in ViewB
should navigate to ViewC
, presenting the details of the selected Item
.
The navigation to ViewC
is misbehaving. When I tap an Item
in ViewB
, ViewC
is shown briefly and then the view immediately navigates back to ViewB
. The navigation stack has ViewC
before ViewB
. Stack: [ViewA, ViewC, ViewB]
The minimal reproducible example:
struct Item: Identifiable, Hashable {
let id = UUID()
let title: String
let description: String
}
struct ViewA: View {
var body: some View {
NavigationStack {
NavigationLink("Go to ViewB") {
ViewB()
}
}
}
}
struct ViewB: View {
let items: [Item] = [
Item(title: "Item 1", description: "This is item 1"),
Item(title: "Item 2", description: "This is item 2")
]
var body: some View {
List(items, id: \.id) { item in
NavigationLink(value: item) {
Text(item.title)
}
}
.navigationDestination(for: Item.self) { item in
ViewC(item: item)
}
}
}
struct ViewC: View {
let item: Item
var body: some View {
Text(item.description)
}
}
I expect to navigate directly to ViewC
when an Item
is selected in ViewB
and the back button should take me back to ViewB
. The stack should be [ViewA (root), ViewB, ViewC]
.
What caused the misbehaviour and how can I resolve this?
You can modify the code of ViewB as follows:
struct ViewB: View {
let items: [Item] = [
Item(title: "Item 1", description: "This is item 1"),
Item(title: "Item 2", description: "This is item 2")
]
var body: some View {
List(items) { item in
NavigationLink {
ViewC(item: item)
} label: {
Text(item.title)
}
}
}
}