Hello,
I used the core data method from project 12 in 100 days of SwiftUI of turning the NSSet? into an Array of elements, for looping.
However, when I perform a .onDelete on the list of elements that result from the NSSet?, Core Data only delete elements from the underlying NSSet; core data does not seem to delete that particular, individual instance of an element from storage. How does one achieve a complete delete of that individual element?
For context:
I'm building a list and saving my data in the core data framework.
My data file has 3 elements: a contract element, an invoice element and a client element. One contract can have one client and many invoices.
The main view (1) has a list of contracts.
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: []) var contracts: FetchedResults<Contract>
var body: some View {
NavigationStack {
List {
NavigationLink {
DetailContract(contract: contract, client: contract.client)
} label: {
ContractListRow(contract: contract, client: contract.client)
}.sheet(isPresented: $addSheetShow, content: {
AddContractForm()
})
}
...
I @FetchRequest a list of contracts and loop through them. On my next view (2 - DetailContractView), I pass the individual contract as an @ObservedObject. In my DetailContractView (2) I pass the contract element further to a third view (3) which presents a list of invoices.
Third (Last) View:
struct InvoiceList: View {
@Environment(\.managedObjectContext) var moc
@Environment(\.dismiss) var dismiss
@ObservedObject var contract: Contract
@ObservedObject var client: Client
@State var filterString = ""
@State var addSheetShow = false
var body: some View {
NavigationStack {
List {
ForEach(contract.invoiceArray, id:\.self) { invoice in
InvoiceListRow(invoice: invoice, client: client)
}.onDelete(perform: deleteInvoice)
}
[...]
func deleteInvoice (at offsets: IndexSet) {
for index in offsets {
let invoice = contract.invoiceArray[index]
moc.delete(invoice)
}
try? moc.save()
}
About invoiceArray: To loop through the invoices, in the NSManagedObject subclass, I converted the NSSet? to an Array of Invoices:
extension Contract {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Contract> {
return NSFetchRequest<Contract>(entityName: "Contract")
}
@NSManaged public var currency: String?
@NSManaged public var registrationNumber: String?
@NSManaged public var registrationSerial: String?
@NSManaged public var client: Client
@NSManaged public var invoice: NSSet?
[...]
public var invoiceArray: [Invoice] {
let set = invoice as? Set<Invoice> ?? []
return set.sorted {
$0.wrappedInvoiceNumber < $1.wrappedInvoiceNumber
}
}
}
The issue is that whenever I delete a list element from invoiceArray, I only seem to be deleting only an element from the NSSet, and not that particular instance of an invoice.
I found this out when I added in my main view a @FetchRequest for all the invoices stored in core data, for a separate list of invoices in order of date. I then found out that even though I've been deleting elements off the list of invoices, Core data kept storing all the invoices previously deleted from my lists.
Please help me to determine how I should proceed about this.
Thank you!