Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to implement.onDelete and .onMove functionality to Core Data-backed .listStyle(GroupedListStyle()) in SwiftUI?

I'm able to get a Core Data backed flat list working (with no .listStyle modifier) with delete and move functionality.

But when I tried to make list grouped

}.listStyle(GroupedListStyle())

the wheels fall off conceptually. The onDelete modifier parameter has a function signature of IndexSet? -> Void. So I can't pass in the object to be deleted.

onMove is essentially the same problem, except worse. Both modifiers rely on a data source assumed to be a flat array of sequential values which can be accessed by IndexSet subscription. But I can't think how to build a grouped list using a flat datasource.

enter image description here

My view body looks like this:

//I'm building the list using two independent arrays. This makes onDelete impossible to implement as recommended

ForEach(folders, id: \.self) { folder in 
                    Section(header: Text(folder.title) ) {
                        ForEach(self.allProjects.filter{$0.folder == folder}, id: \.self){ project in
                            Text(project.title)
//this modifier is where the confusion starts:
                        }.onDelete(perform: self.delete) 
                    }
                }

            }.listStyle(GroupedListStyle())
    func delete (at offsets: IndexSet) {
        //        ??.remove(atOffsets: offsets)
        //Since I use two arrays to construct group list, I can't use generic remove at Offsets call. And I can't figure out a way to pass in the managed object.

    }

      func move (from source: IndexSet, to destination: Int) {
    ////same problem here. a grouped list has Dynamic Views produced by multiple arrays, instead of the single array the move function is looking for.
        } 
like image 489
Small Talk Avatar asked Oct 25 '25 20:10

Small Talk


1 Answers

Can't you store the result of the filter and pass that on inside .onDelete to your custom delete method? Then delete would mean deleting the items inside the IndexSet. Is moving between sections possible? Or do you just mean inside each folder? If only inside each folder you can use the same trick, use the stored projects and implement move manually however you determine position in CoreData.

The general idea is the following:

import SwiftUI

class FoldersStore: ObservableObject {
    @Published var folders: [MyFolder] = [

    ]

    @Published var allProjects: [Project] = [

    ]

    func delete(projects: [Project]) {

    }
    func move(projects: [Project], set: IndexSet, to: Int) {

    }
}

struct MyFolder: Identifiable {
    let id = UUID()
    var title: String
}

struct Project: Identifiable {
    let id = UUID()
    var title: String
    var folder: UUID
}

struct FoldersAndFilesView: View {
    var body: some View {
        FoldersAndFilesView_NeedsEnv().environmentObject(FoldersStore())
    }
}

struct FoldersAndFilesView_NeedsEnv: View {
    @EnvironmentObject var store: FoldersStore

    var body: some View {
        return ForEach(store.folders) { (folder: MyFolder) in
            Section(header: Text(folder.title) ) {
                FolderView(folder: folder)
            }
        }.listStyle(GroupedListStyle())
    }
}

struct FolderView: View {
    var folder: MyFolder
    @EnvironmentObject var store: FoldersStore

    func projects(for folder: MyFolder) -> [Project] {
        return self.store.allProjects.filter{ project in project.folder == folder.id}
    }

    var body: some View {
        let projects: [Project] = self.projects(for: folder)

        return ForEach(projects) { (project: Project) in
            Text(project.title)
        }.onDelete {
            self.store.delete(projects: $0.map{
                return projects[$0]
            })
        }.onMove {
            self.store.move(projects: projects, set: $0, to: $1)
        }
    }
}
like image 116
Fabian Avatar answered Oct 27 '25 15:10

Fabian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!