I'm working on a Core Data / CloudKit public Database.
Apple recommends not to delete the object but to set a variable e.g. isTrashed to true.
After that a predicate should be set for the FetchRequest so that this object is no longer displayed.
So in my view I set this variable to true when an object is deleted and this is also set correctly. Here is the query directly from the dashboard:
Unfortunately the predicate doesn't work as it should and the object is still displayed. Can anyone tell me what I am doing wrong?
Fetch Request
static var productsByName: NSFetchRequest<Product> {
/// create Request
let request: NSFetchRequest<Product> = Product.fetchRequest()
/// sortDescriptor
request.predicate = NSPredicate(format: "isTrashed = false") // <-- predicate for isTrashed
request.sortDescriptors = [NSSortDescriptor(keyPath: \Product.name, ascending: true)]
return request
}
ContentView.swift
struct ContentView: View {
@SectionedFetchRequest(fetchRequest: ContentView.productsByName, sectionIdentifier: \Product.manufacturer?.name)
var products: SectionedFetchResults<String?, Product>
var body: some View {
NavigationStack {
List {
ForEach(products) { section in
Section(header: Text(section.id ?? "unassigned")) {
ForEach(section) { product in
NavigationLink(destination: productDetailView(product: product)){
Text(product.name ?? "na")
}
}
.onDelete { rows in
for row in rows {
let product = section[row]
if storageProvider.persistentContainer.canDeleteRecord(forManagedObjectWith: product.objectID) {
storageProvider.deleteProduct(product)
} else {
product.isTrashed = true // <-- here the value for isTrashed is set
do {
try storageProvider.persistentContainer.viewContext.save()
} catch {
storageProvider.persistentContainer.viewContext.rollback()
print("Failed to save context: \(error)")
}
}
}
}
}
}
}
}
}
}
info 1
additional info:
I added this code to the detailView of the products to check if the value is set correct:
Text("is trashed: \(product.isTrashed ? "true" : "false")")
... and yes it is:
info 2
I also tried these for the query:
request.predicate = NSPredicate(format: "isTrashed = 0")request.predicate = NSPredicate(format: "isTrashed = FALSE")request.predicate = NSPredicate(format: "isTrashed = NO")request.predicate = NSPredicate(format: "isTrashed = 0")request.predicate = NSPredicate(format: "isTrashed == FALSE")request.predicate = NSPredicate(format: "isTrashed == NO")request.predicate = NSPredicate(format: "%K = %@", argumentArray: [#keyPath(Product.isTrashed), false])request.predicate = NSPredicate(format: "%K == %@", argumentArray: [#keyPath(Product.isTrashed), false])
So I don't think the query itself is the problem :/
info 3
but for example this predicate directly on the view is working:
.onReceive(productName.$debounced) { query in
/// don't filter when searchbar is empty
guard !query.isEmpty else {
products.nsPredicate = nil
return
}
/// set filter when someone searches
products.nsPredicate = NSPredicate(format: "%K CONTAINS[cd] %@", argumentArray: [#keyPath(Product.name), query])
}
That's why I don't understand why the predicate on the FetchRequest isn't working.
Does anyone have an idea?