Here is the code if you don't understand
struct cartView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [], animation: .default) private var products: FetchedResults<Prod>
let columns = [GridItem(.flexible()), GridItem(.flexible())]
@State var indx = 0
var body: some View {
NavigationView {
ScrollView {
VStack {
LazyVGrid(columns: columns) {
ForEach(products, id: \.self) {prod in
let prodItems = Product(name: prod.name ?? "Undefined", price: prod.price ?? "Undefined", type: "type", brand: prod.brand ?? "Undefined", images: [prod.image!,""])
ZStack {
Cells(product: prodItems)
// I want the button below delete the item of the
// button pressed with the function below
Button(action: {}) {
Image(systemName: "xmark.bin.circle")
.resizable()
.frame(width: 30, height: 30)
.foregroundColor(.red)
.background(.black)
.clipShape(RoundedRectangle(cornerRadius: 20))
.offset(x: 60, y: 45)
}
}
}
}
}
}
.navigationTitle("Cart")
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { products[$0] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
}
}
}
so the question here is the button there in the forEach loop to delete the item that the user pressed the button and I know how to do it, but what I don't know is how to get the index of the item and pass it in the function.
CodePudding user response:
You don't actually need the index if you're issuing the delete instruction from within your loop, as your NSManagedObjectContext
instance has a delete(_:)
method that takes the object itself. That change will propagate through your @FetchRequest
object automatically, your SwiftUI view will update to show the collection without the now-deleted object.
So your button action becomes:
Button(action: {
viewContext.delete(prod)
}) {
Image(systemName: ...)
// etc.
}
Note that while you'll see the effect straight away, the deletion will only be in memory until you call save
on the managed object context.
In my CoreData apps, I tend to save my changes separately, for example when the app is about to go into the background. But if you want to trigger a save immediately the object is removed, that's straightforward enough:
Button(action: {
viewContext.delete(prod)
try? viewContext.save()
}) {
Image(systemName: ...)
// etc.
}
NB: the documentation for NSManagedObjectContext.save()
says that you should check the hasChanges
property before attempting to save, but as you've just made a change in the line above, that's not necessary in this particular example.