SwiftUI List with Sections fetched from Core Data
Asked Answered
S

1

8

Back in objective-c, I could fetch a sectioned list of objects from Core Data using something like this:

self.fetchedResultsController = [[NSFetchedResultsController alloc]
         initWithFetchRequest:fetchRequest
         managedObjectContext:managedObjectContext
           sectionNameKeyPath:@"ispurchased"
                    cacheName:nil];

And then the NSFetchedResultsController would automatically give me the data in sections and rows.

I'm experimenting with SwiftUI for the first time and I'm trying to figure out how to achieve a sectioned List like that. I've found lots of examples that use some canned array data that is pre-structured in the sectioned fashion, but I can't figure out how to do a sectioned FetchRequest nor how to integrate that with the List.

struct EasyModeList: View {
    @FetchRequest(
        sortDescriptors: [
            NSSortDescriptor(keyPath: \EasyMode.ispurchased, ascending: true),
            NSSortDescriptor(keyPath: \EasyMode.ispurchasable, ascending: false),
            NSSortDescriptor(keyPath: \EasyMode.name, ascending: true),
        ],
        animation: .default)
    var easymodes: FetchedResults<EasyMode>

    @Environment(\.managedObjectContext)
    var viewContext

    var body: some View {
        List {
            ForEach(self.easymodes, id: \.self) { easymode in
                NavigationLink(
                    destination: DetailView(easymode: easymode)
                ) {
                    VStack {
                        Text("\(easymode.name!)")
                    }
                }
            }
        }
    }
}

Does SwiftUI easily support those kinds of sectioned lists? Is there a different paradigm that I should be shifting my brain to?

Salted answered 28/3, 2020 at 19:57 Comment(0)
K
4

I am also looking for a proper solution to this. For now I'll share what I've tried. My sections are by string titles, but I'll adapt it for your data.

@FetchRequest(...) var managedEasyModes: FetchedResults<EasyMode>

private var easyModes: [String: [EasyMode]] {
    Dictionary(grouping: managedEasyModes) { easymode in
        easymode.ispurchased ? "Purchased" : "Not Purchased"
    }
}

private var sections: [String] {
    easyModes.keys.sorted(by: >)
}

var body: some View {
    ForEach(sections, id: \.self) { section in
        Section(header: Text(section)) {
            ForEach(easyModes[section]!) { easyMode in
                NavigationLink(destination: EasyModeView(easyMode: easyMode)) {
                    EasyModeRowView(easyMode: easyMode)
                }
            }
        }
    }
}
Karp answered 23/7, 2020 at 2:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.