I have an issue with NavigationStack
and .navigationDestination
. This is a slightly simplified version of a view body in my app.
VStack {
// other views
List {
Section("Recent Activity") {
ForEach(viewModel.posts) { post in
NavigationLink(value: post) {
PostListItemView(post: post)
}
}
}
Section("Reading List") {
ForEach(viewModel.books) { book in
NavigationLink(value: book) {
ReadingListItemView(
title: book.title,
authors: book.authors,
familiarity: book.familiarity
)
}
}
}
}
}
.navigationDestination(for: Book.self) { book in
BookDetailsView(book: book, familiarity: .constant(book.familiarity))
}
.navigationDestination(for: Post.self) { post in
PostDetailView(post: post)
}
Both Book
and Post
conform to Hashable
.
Tapping on a ReadingListItemView
results in the following error message:
A NavigationLink is presenting a value of type “Book” but there is no matching navigationDestination declaration visible from the location of the link. The link cannot be activated.
Note: Links search for destinations in any surrounding NavigationStack, then within the same column of a NavigationSplitView.
The the view is a child of a Navigation Stack. There is no other navigationDestination(for: Book.self)
in the stack. The tapping a PostListItemView
in the adjacent section behaves as expected. Moving the navigationDestination
to the relevant List
or Section
don’t improve the situation.
The only things I can think of that might be confusing the system are:
- The parent of the view code above is itself a list item, so perhaps list virtualization is a problem somehow.
- The root view is a
TabView
with three tabs. Each tab has its own navigation stack. An adjacent tab does have anavigationDestination(for: Book.self)
in it. - If I replace each tab’s
NavigationStack
with a single stack that wraps the wholeTabView
, navigation works better, but it still exhibits some strange pushing behavior where views are pushed onto the stack that weren’t requested AFAICT.
I’d appreciate any insight into what I’m missing.
2
Answers
My problem was ultimately that there were too many
navigationDestination(for: Hashable, destination:)
modifiers in the navigation stack in some circumstances. The problem was They would occasionally conflict with one another, resulting in strange error messages like:My ultimate solution was to move most of the
navigationDestination
modifiers nearer the root of the navigation stack, which made some of the more convoluted parts of my navigation hierarchy more obvious.Here is a functional MRE and it does work like expected. So the issue might be somewhere else in code you don’t show.