I have a typical NavigationSplitView
layout in my app:
NavigationSplitView {
List(0..<3, selection: $selection) { item in
Label(MainDataType.data[item].name, systemImage: MainDataType.data[item].icon)
}
} content: {
switch selection {
case 0: StudentsView()
case 1: WorksView()
// More options here...
}
} detail: {
NoDataView() // <- Just for main view first presentation.
}
Sidebar
and Content
views work perfectly fine. For Detail
view, I overwrite default NoDataView
with, for example, StudentDetail
, from StudentsView
selection:
struct StudentsView() {
...
List(students, id:\.self) { student in
NavigationLink(destination: NavigationStack { // <- In order to get navigation inside SplitView detail column.
StudentDetailView(student: student)}) {
StudentCellView(student: student)
...
As in StudentDetailView
I have deeper NavigationLinks
(see attached gif).
This layout has been working until iOS17. Now it still works almost in every case, but this console message appears:
A NavigationLink is presenting a NavigationStack onto a column. This construction is not supported. Consider instead just presenting a new root view which will replace that of an existing stack in the column, or else the column itself if there is no NavigationStack in the target column. If there is a stack in the target column, appending to that stack's path is another option.
I'm testing these navigation changes:
struct StudentsView() {
...
List(students, id:\.self) { student in
NavigationLink(destination: StudentDetailView(student: student)) {
StudentCellView(student: student)
...
This way no console message is shown, and deep NavigationLinks
work (more or less), but with no navigation behavior (navigating back, animation...).
So I'm now struggling with this two questions:
- Is there any way of getting a complete full-support
NavigationStack
inside detail view ofNavigationSplitView
? - If so, what's the code to get it work?
- If not, what are the alternatives?
Your example looks a little like the three-column example from Apple.
In general, you would want to have your
NavigationStack
as the root view in thedetails
part of the split view. Inside theNavigationStack
, you would then choose which view should be displayed, based on what has been selected in thecontent
part. This is exactly what the part in the error message means:Here is a minimal example of what I mean:
In your case, you would have your students list in the
content
part, but you would need to replace theNavigationLink
s in the list by using theList(selection:)
initializer. Based on this selection, you can display the correct student details in thedetails
section (inside theNavigationStack
there).Also, for deeper navigation hierarchies, you can take a look at NavigationStack(path:root:), which works quite nicely together with the
NavigationLink(value:label:)
and the.navigationDestination(for:destination:)
modifier. You can just create your ownDestination
enum (make it conform toHashable
) and use an array ([Destination]
) as yourpath
.