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

How to also delete an element from core data storage when deleting an element from the underlying NSSet array?

Forums > SwiftUI

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!

2      

You deleted it from the managed object context, but you haven't told the UI that the moc changed.

You'd need to make your invoiceArray an @ObservedObject and then @Published in your CoreData extension.

2      

call moc.save() in deleteInvoice function

2      

Actually, moc.save() is in that function, just the indenting wasn't fixed.

OP, handy tip:

  • Select text to re-indent
  • Editor -> Structue -> Re-Indent

2      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

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.