I’ve filed this bug with Apple (FB12119791) since I’m pretty sure it’s not a mistake in my code, but posting here both for posterity and to see if anyone has found a solution. It’s also hard to describe, so the attached code sample is probably a good place to start.
When conditionally rendering a row outside of a section alongside a section of rows in NavigationSplitView’s sidebar, an application crash can be consistently reproduced.
Steps to reproduce
- Create a SwiftUI view with a NavigationSplitView. For the split view’s sidebar, create a list with navigable elements and a conditionally-rendered, non-navigable element (i.e. a view that only renders when a boolean state value is true)
- Navigate into a navigable element’s destination, then back to the list
- Toggle the conditional state value off to hide the conditionally-rendered element
- Try to navigate into a navigable element’s destination again
Expected result
The navigation view should segue to the chosen navigable element’s destination
Actual result
The app (or Xcode preview) crashes at the app’s @main entry point
Code sample
import SwiftUI
fileprivate struct Item: Identifiable, Hashable {
let id = UUID()
}
fileprivate let items = (0...10).map { _ in Item() }
struct ListSelectionConditionalViewCrashExample: View {
@State var showConditionalView = true
@State var selectedItem: UUID?
var body: some View {
NavigationSplitView {
List(selection: $selectedItem) {
Section {
Label("Tap a row in the navigable rows section below", systemImage: "1.circle")
Label("Return to this screen", systemImage: "2.circle")
Label("Toggle the control below **off**", systemImage: "3.circle")
Label("Tap a row in the navigable rows section below", systemImage: "4.circle")
Label("Observe the app crash", systemImage: "exclamationmark.circle")
.foregroundStyle(.red)
Text("Note this only happens when navigable and non-navigable rows appear in separate sections")
Toggle(isOn: $showConditionalView.animation()) {
Text("Render conditional view")
}
} header: {
Text("Instructions")
}
if showConditionalView {
Text("Conditional view")
}
Section {
ForEach(items) { item in
Text(item.id.uuidString)
.tag(item.id)
}
} header: {
Text("Navigable rows")
}
}
.navigationTitle("Navigation List Crash")
} detail: {
if let selectedItem,
let item = items.first(where: { $0.id == selectedItem }) {
Text(item.id.uuidString)
.navigationTitle("Detail View")
} else {
Text("No selection")
}
}
}
}
struct ListSelectionConditionalViewCrashExample_Previews: PreviewProvider {
static var previews: some View {
ListSelectionConditionalViewCrashExample()
}
}