How to implement multiple selection types in NavigationSplitView?

In the sidebar column of the NavigationSplitView I'd like to have several sections. All the items are fetched with Core Data.

  • View all photos (Photos entity in Core Data)
  • Folder (Folder entity in Core Data)
    • Folder A
    • Folder B
    • Folder C
  • Tags (Tag entity in Core Data)
    • Cat
    • Dog

In the content view, I'd like show the items based on the selection in the sidebar. I tried the following with some success but I think there should be another way of doing this.

NavigationSplitView() {
   List(selection: $navigationModel.selectedCategory, content: {

      NavigationLink(value: Category(type: .all, predicate: NSPredicate(value: true), title: "View all items") ) {
                    Text("View all items")
                }

  Section {
     ForEach(folders){ folder in
         NavigationLink(value: Category(type: .folder, predicate: NSPredicate(format: "folder == %@", folder), title: folder.name) ) {
         FolderRow(folder: folder)
// ... and so on. Another section for tags

And in the content:

ZStack{
   List(selection: $navigationModel.selectedPhoto) {
      ContentView(photos: FetchRequest(
                  sortDescriptors: [sortDescriptor],
                  predicate: navigationModel.selectedCategory?.predicate,
                  animation: .default)
//....

How can refractor this code with a better solution? The problem that I'm encountering is that the selection argument in the List accepts only one type of object. But I want to select more that one type of object. Another issue is that this solution won't conform to Codable if I'm thinking correctly and reseting the app state on the next launch would be cumbersome.

Anyone can please help with this? I'd like to mention that when using NavigationStack instead of NavigationSplitView, there is the possibility of using .navigationDestination<D, C>(for data: D.Type, destination: @escaping (D) -> C). So it would be possible to present different view for different selection value types. But it seems to me that NavigationSplitView is limited in this scope.

For anyone else passing through. I use an enum with associated values for $navigationModel.selection like so:


@Observable
final class NavigationModel {
    ...
    enum SelectedItem: Hashable {
        case folder(Folder.ID)
        case tag(Tag.ID)
    }

    ...

    var selection: SelectedItem?

    ...
}

In my sidebar view:

List(selection: $nabvigationModel.selection) {
    Section {
        ForEach(folders) {
            Text(folder.name)
                .id(folder.id)
        }
    } header: { Text("Folders") }

    Section {
        ForEach(tags) {
            Text(tag.label)
                .id(tag.id)
        }
    } header: { Text("Tags") }
}

NavigationSplitView:

NavigationSplitView {
    SidebarView()
} detail: {
    switch navigationModel.selection {
        case .folder(let id):
              // fetch folder with ID & render...
        case .tag(let id):
              // fetch tag with ID & render...
        default:
             Text("No Selection"
    }
}

How to implement multiple selection types in NavigationSplitView?
 
 
Q