I'm trying to update an older app to use the new NavigationSplitView and NavigationLink, but trying to wrap my head around the proper way to do it when the sidebar has a hierarchy of child objects and I want to update the detail view from a distant child object. For example, based on the WWDC2022 example project Navigation Cookbook I tried the following and it didn't work:
TestApp.swift
@main
struct TestApp: App {
@StateObject var appState = AppState()
var body: some Scene {
WindowGroup {
NavigationSplitView {
ProjectListView()
} detail: {
if let chapter = appState.chapter {
ChapterDetailView(chapter: chapter)
} else {
Text("Pick a Chapter")
}
}
}
}
}
ChapterListView.swift < A distant (3 levels down) sibling of ProjectListView()
List(selection: $appState.chapter) {
ForEach(chapters) { chapter in
NavigationLink(chapter.title ?? "A Chapter", value: chapter)
}
}
appState.swift
class AppState: ObservableObject {
@Published var chapter: Chapter?
}
I'm sure I'm just not understanding the basics of how the new way of doing navigation works. Yes, I am targeting iOS16
This is a known bug in beta 1. To workaround, the logic in the detail section needs to be wrapped in a ZStack. From the release notes:
Conditional views in columns of NavigationSplitView fail to update on some state changes. (91311311) Workaround: Wrap the contents of the column in a ZStack. TestApp works if changed to this:
@main
struct TestApp: App {
@StateObject var appState = AppState()
var body: some Scene {
WindowGroup {
NavigationSplitView {
ProjectListView()
} detail: {
// Wrap in a ZStack to fix this bug
ZStack {
if let chapter = appState.chapter {
ChapterDetailView(chapter: chapter)
} else {
Text("Pick a Chapter")
}
}
}
}
}
}