UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Generic @FetchRequest -> How can I get .onDelete Modifier

Forums > SwiftUI

Hello! I successfully made a generic fetchRequest like Paul is showing in Dynamically filtering @FetchRequest with SwiftUI - CoreData SwiftUI Tutorial 6/7. All is working absolute fine but i cannot implement the .onDelete modifier. Does anyone have a solution for that? Please find my code below. Thanks a lot in advance! Martin

My FetchRequest View:

import CoreData
import SwiftUI

struct FetchedListView<T: NSManagedObject, Content: View>: View {
    @FetchRequest var fetchRequest: FetchedResults<T>
    let content: (T) -> Content

    var body: some View {
        List(fetchRequest, id: \.self) { item in
            self.content(item)
        }
    }

    init(filterKey: String, filterValue: String, sortingKey: String, sortAscending: Bool, @ViewBuilder content: @escaping (T) -> Content) {
        _fetchRequest = FetchRequest<T>(sortDescriptors: [NSSortDescriptor(key: sortingKey, ascending: sortAscending)], predicate: filterValue == "" ? nil : NSPredicate(format: "%K BEGINSWITH[c] %@", filterKey, filterValue))
        self.content = content
    }
}

My Content View:

struct ContentView: View {

    @EnvironmentObject var data:  DataController
    @Environment(\.managedObjectContext) var moc

//    @FetchRequest(sortDescriptors: [
//        SortDescriptor(\.title),
//        SortDescriptor(\.author)
//    ]) var books: FetchedResults<Book>
//    
//    @State var sortDescriptor: NSSortDescriptor = NSSortDescriptor(keyPath: \Book.title, ascending: true)
    @State private var sortKey = "title"
    @State private var ascent = true
    @State private var filterKey = "title"

    @State private var sortType: Int = 0
    @State private var showingAddScreen = false

    enum Sort: String {
        case title, author
    }
    enum Filter: String {
        case title, author, genre
    }
    var body: some View {

        NavigationView {
            FetchedListView(filterKey: filterKey, filterValue: "", sortingKey: sortKey, sortAscending: ascent, content: { (book: Book) in
                NavigationLink {
                    DetailView(book: book)
                } label: {
                    HStack {
                        EmojiRatingView(rating: book.rating)
                            .font(.largeTitle)

                        VStack(alignment: .leading) {
                            Text(book.title ?? "Unknown Title")
                                .font(.headline)
                            Text(book.author ?? "Unknown Author")
                                .foregroundColor(.secondary)
                        }
                    }
                }
            })
            .navigationTitle("Bookworm")
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    EditButton()
                }
                ToolbarItem(placement: .principal) {
                    VStack(alignment: .center) {

                        Menu {
                            Button {
                                sortKey =  Sort.title.rawValue
                                ascent = true
                            } label: {
                                Label("Title", systemImage: "arrow.down")
                            }
                            Button {
                                sortKey =  Sort.title.rawValue
                                ascent = false
                            } label: {
                                Label("Title", systemImage: "arrow.up")
                            }
                            Button("Author") {
                                sortKey = Sort.author.rawValue
                            }
                            Button("Author") {
                                sortKey = Sort.author.rawValue
                            }
                        } label: {
                            Label("Sort", systemImage: "filemenu.and.cursorarrow")
                        }
                    }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        showingAddScreen.toggle()
                    } label: {
                        Label("Add Book", systemImage: "plus")
                    }
                }
            }
            .sheet(isPresented: $showingAddScreen) {
                AddBookView()
            }

        }
    }
//    func deleteBooks(at offsets: IndexSet) {
//        for offset in offsets {
//            let book = books[offset]
//            moc.delete(book)
//        }
//
//        //        //        try? moc.save()
//    }
}

2      

@Bnerd  

I guess your .onDelete should be added on the list i.e.

List(fetchRequest, id: \.self) { item in
            self.content(item)
        }.onDelete(perform: deleteBooks)

Or try like this..

List(fetchRequest, id: \.self) { item in
            self.content(item).onDelete(perform: deleteBooks)
        }

the deleteBooks func should be in the struct FetchedListView and as below:

func deleteBooks(at offsets: IndexSet) {
        for offset in offsets {
            let item = fetchRequest[offset]
            moc.delete(item)
        }
        try? moc.save()
    }

You should add also the below in the FetchedList View file

@Environment(\.managedObjectContext) var moc

Give it a try..

2      

...thanks @Bnerd, unfortunatly it's not working. I triggers following error:

Value of type 'Content' has no member 'onDelete'

or

Value of type 'List<Never, ForEach<FetchedResults<T>, Fetchedesults<T>.Element Content>>' (aka 'List<Never, ForEach<FetchedResults<T>, T, Content>>') has no member 'onDelete'

2      

@Bnerd  

Ok change it to the below:

List {
ForEach(fetchRequest, id: \.self) { item in
            self.content(item)
        }.onDelete(perform: deleteBooks)
}

3      

Dearest @Bnerd, you are a star! thanks a lot, all is working now! and i learned a lot! Regards, Martin

2      

TAKE YOUR SKILLS TO THE NEXT LEVEL If you like Hacking with Swift, you'll love Hacking with Swift+ – it's my premium service where you can learn advanced Swift and SwiftUI, functional programming, algorithms, and more. Plus it comes with stacks of benefits, including monthly live streams, downloadable projects, a 20% discount on all books, and free gifts!

Find out more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.