After a lot of trial and error, and gaining a deeper understanding of how NavigationSplitView, NavigationStack, and NavigationPath can work together, I came up with the following solution, that allows me to push a list onto an existing one, and use NavigationSplitView's detail: to push a detail. While this doesn't support recursive-lists (more than two levels deep), that's not a requirement for my usage.
The "trick" that I learned that allowed this to work, was to use NavigationPath within a NavigationStack in my NavigationSplitView sidebar, in order to push another list onto the detail.
In addition, the trigger of detail: in a NavigationSplitView is from the List(selection:) within the side-bar.
Because I am using the same Binding within both my List and its sub-list, the NavigationSplitView pushes the detail onto the highest stack.
Here's the final result. working on iPhone and iPad:
In order to push a LocationListView onto an existing one, I incorporated NavigationPath:
ContentView
struct ContentView: View {
@State private var navigationPath = NavigationPath()
@State private var selectedItem: Location?
@State private var columnVisibility = NavigationSplitViewVisibility.doubleColumn
var body: some View {
NavigationSplitView(columnVisibility: $columnVisibility) {
NavigationStack(path: $navigationPath) {
LocationListView(
locationData: LocationSampleData(
locations: LocationSampleData.sampleLocations,
locationGroups: LocationSampleData.sampleLocationGroups
), selectedItem: $selectedItem,
navigationPath: $navigationPath)
.navigationDestination(for: LocationGroup.self) { locationGroup in
LocationListView(
locationData: LocationSampleData(locations: locationGroup.locations), selectedItem: $selectedItem,
navigationPath: $navigationPath
)
}
}
} detail: {
if let selectedItem = selectedItem {
LocationDetailView(selectedLocation: selectedItem)
}
}
}
}
LocationListView
struct LocationListView: View {
var locationData: LocationSampleData
@Binding var selectedItem: Location?
@Binding var navigationPath: NavigationPath
var body: some View {
List(selection: $selectedItem) {
if let locations = locationData.locations {
ForEach(locations) { location in
NavigationLink(value: location) {
Text(location.name)
.bold()
}
}
}
if let locationGroups = locationData.locationGroups {
ForEach(locationGroups) { locationGroup in
Button(action: {
navigationPath.append(locationGroup)
}) {
Text(locationGroup.name)
.bold()
.foregroundStyle(.red)
}
}
}
}
.navigationTitle("Saturday Spots")
.navigationBarTitleDisplayMode(.large)
}
}
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags: