Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI List with Sections fetched from Core Data

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?

like image 454
Kenny Wyland Avatar asked Nov 06 '22 08:11

Kenny Wyland


1 Answers

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)
                }
            }
        }
    }
}
like image 180
Michael Ozeryansky Avatar answered Nov 15 '22 16:11

Michael Ozeryansky