I am trying to implement a SwiftUI list for a sidebar view which has at least 3 different types of data points: a) a fixed list of enums, b) a list of 'tags' coming from a @FetchRequest using Core Data, c) a similar list of 'groups' coming from a different @FetchRequest.
I'm struggling with how to handle multiple selection with List in this setup. The user should be able to select from different sections (and I get change notifications to fine-tune the handling). I have tried making the 'selection' type to be UUID, and setting the id for each leaf view explicitly, but it doesn't seem to work (I don't the selection highlight).
This is the list I made:
struct CombinedListView: View {
@FetchRequest(
entity: CJTag.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \CJTag.displayOrder, ascending: true)]
)
var tags: FetchedResults<CJTag>
@FetchRequest(
entity: PrivateGroups.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \PrivateGroups.displayOrder, ascending: true)]
)
var groups: FetchedResults<PrivateGroups>
@State private var selectedItems = Set<UUID>()
var body: some View {
NavigationView {
VStack {
List(selection: $selectedItems) {
// section for Tabs
Section(header: Text("Main Tabs")) {
ForEach(MainTab.allCases, id: \.rawValue) { tab in
Text(tab.rawValue)
.id(tab.id)
}
}
// Section for Tags
if !tags.isEmpty {
Section(header: Text("Tags")) {
ForEach(tags) { tag in
Text(tag.tagName ?? "Tag")
.id(tag.objectID.uriRepresentation().absoluteString) // Directly tag with UUID
.contentShape(Rectangle())
}
}
}
// Section for Groups
if !groups.isEmpty {
Section(header: Text("Groups")) {
ForEach(groups) { group in
Text(group.groupName ?? "Group")
.id(group.objectID.uriRepresentation().absoluteString)
.contentShape(Rectangle())
}
}
}
}
.listStyle(SidebarListStyle())
.navigationTitle("Selectable List")
}
}
}
}
I know that if I just had NSManagedObjects in the list, I could set the 'selection' type to be NSManagedObjectID and it would work. But I needed it to support a list of enum cases as well.
I tried setting the tag for each row view as well (using the same stuff as id modifier), but that doesn't work either. I'm sure it's a case of mismatched 'types' for selection, but I can't figure out the best setup to accomplish this.
EDIT:
Added code for MainTab:
// Enum for Main Tabs
enum MainTab: String, CaseIterable, Identifiable {
case home = "Home"
case favorites = "Favorites"
case settings = "Settings"
case profile = "Profile"
case help = "Help"
var id: String { rawValue }
var iconName: String { rawValue.lowercased() }
}
NavigationViewis deprecated useNavigationStackinstead..id(tag.objectID.uriRepresentation().absoluteString)does not seem to be of typeUUID, more like aString. You could/should try using.tag(UUID type here)instead of.id(...). And ensure thattab.idis of typeUUID. You mentionedNSManagedObjects, is this for a macOS App only? Can you show the code forMainTab.MainTabenum code. Yes, this is for macOS only. Also, theobject.objectID.uriRepresentation().absoluteStringshould be unique, so does that qualify as a UUID type itself, or do I have to add that conformance separately (if so, how)?NSManagedObjectsalready have automatic conformance toIdentifiable, usingNSManagedObjectIDUUIDis a type different toString. Just because the strings are unique does not make them of typeUUID. So try this instead,var selectedItems = Set<String>()with.tag(...).tag(...)or.id(...)