I'm working on a SwiftUI based application for MacOS. I have a TabView component with two child Tab
components. These Tab
components display a List
, each derived from an array of elements.
While the application is running, clicking on the tabs in the TabView
should switch between the views of different Lists. What I'm experiencing is that switching between the tabs causes a FAULT. With errors:
Row index 1 out of row range (numberOfRows: 1) for <SwiftUI.SwiftUIOutlineListView: 0x1299d2000>
Followed by:
(
0 CoreFoundation 0x000000019e096e80 __exceptionPreprocess + 176
1 libobjc.A.dylib 0x000000019db7ecd8 objc_exception_throw + 88
2 AppKit 0x00000001a1c744e8 -[NSTableRowData _availableRowViewWhileUpdatingAtRow:] + 0
3 SwiftUI 0x00000001cd8953f4 $s7SwiftUI0A17UIOutlineListViewC11removeItems2at8inParent13withAnimationy10Foundation8IndexSetV_ypSgSo07NSTableeL7OptionsVtF + 1232
...
...
)
And finally:
FAULT: NSTableViewException: Row index 1 out of row range (numberOfRows: 1) for <SwiftUI.SwiftUIOutlineListView: 0x1299d2000>; (user info absent)
This error happens when switching between the two tabs, defined thusly:
@main
struct MyApp: App {
@State var rootDirectory: URL
@State var selectedItem: URL
@State var projectNavItems: [NavigationItem] = []
@State var jotNavItems: [NavigationItem] = []
@State var importerIsPresented: Bool = false
let fileManager = FileManager.default
init() {
rootDirectory = URL(string: FileManager.default.currentDirectoryPath)!
selectedItem = URL(string: FileManager.default.currentDirectoryPath)!.appendingPathComponent("README.md")
}
var body: some Scene {
WindowGroup {
NavigationSplitView {
TabView {
Tab("Projects", systemImage: "tray.and.arrow.down.fill") {
List(projectNavItems, selection: $selectedItem) {
// Changing this NavigationLink line to Text($0.title) makes no difference
NavigationLink($0.title, value: $0.id)
}
}
Tab("Jots", systemImage: "tray.and.arrow.up.fill") {
List(jotNavItems, selection: $selectedJot) {
// Can be written as Text($0.title) with no change in behavior
NavigationLink($0.title, value: $0.id)
}
}
}
} detail: {
Editor(for: selectedItem)
}
.fileImporter(
isPresented: $importerIsPresented,
allowedContentTypes: [UTType.folder],
allowsMultipleSelection: false
) { result in
// Code that gets a security scoped resource and populates the
// projectNavItems: [NavItem] and jotNavItems: [NavItem]
// arrays
}
}
.commands(content: {
CommandGroup (before: .newItem) {
Button("Open Journal...") {
importerIsPresented.toggle()
}
}
})
}
}
The error only happens when both Tab
views are populated by a List
. If the Tab view have different child components, say a List
, and a ForEach
of Text
components, switching between the tabs doesn't produce this error. List
views with Text
child components also produce this error.
Here are screenshots of the running application
Once the user selects a directory, we see the first Tab
> List
component populated by contents from the projectNavItems
array:
Clicking on the 'Jots' tab switches to the appropriate tab and correctly lists the items in the jotNavItems
array, except there are additional lines, seemingly showing that there's an issue.
Clicking back on the 'Projects' tab switches back, but now the List
shows only one of the items from the projectNavItems
array.
Finally, clicking on 'Jots' again causes the errors to print in the console and interactivity with the tab components ceases. Last screenshot is representative of this state as the application FAULTS.
This seems like a bug in SwifUI, wondering what workarounds I might be able to implement.
I can provide the full backtrace, I cropped it for content length.