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

SOLVED: Swift UI Core Data - one to many - getting a reference and deleting an entity with .onDelete().

Forums > 100 Days of SwiftUI

Hello,

Just finished the Core Data Chapter, and am interested to know how you would delete one of the candy entities.

I guess it would go something like this ? - but how to you get a refrence to the Country entity that works?

func deleteCandy (at offsets: IndexSet) {
        for offset in offsets {
        let set = countries[0].candyArray[offset]
            moc.delete(set)
        if self.moc.hasChanges{
            try? moc.save()
            }
        }
    }

For

 VStack {
            List {
                ForEach(countries, id: \.self) { country in
                    Section(header: Text(country.wrappedFullName)) {
                        ForEach(country.candyArray, id: \.self) { candy in
                            Text(candy.wrappedName)
                        }
                    }
                }.onDelete(perform: deleteCandy)
            }

Thanks in advance!

3      

hi,

i'm assuming you want to delete candies from a country, and not countries

first, you'll need to move the .onDelete modifier to the inner ForEach; and second, asking to perform a simple function by name doesn't work because it is passed only an IndexSet of offsets of candies -- but you really need to know which country those offsets apply to.

the solution is to use a closure inside the .onDelete modifier to intercept and then re-route those offsets to a deletion function that also knows the country for which the offsets apply. something like this should work:

        List {
            ForEach(countries, id: \.self) { country in
                Section(header: Text(country.wrappedFullName)) {
                    ForEach(country.candyArray, id: \.self) { candy in
                        Text(candy.wrappedName)
                    }
                    .onDelete(perform: { offsets in
                        self.deleteCandies(at: offsets, from: country)
                    })
                }
            }
        }

now you can do the deletion function this way. (note: the removeFromCandy() function is one of the accessors defined by XCode in generating the Country+CoreDataProperties.swift file.)

    func deleteCandies(at offsets: IndexSet, from country: Country) {
        for offset in offsets {
            let candyToDelete = country.candyArray[offset]
            country.removeFromCandy(candyToDelete)
            moc.delete(candyToDelete)
        }
        if moc.hasChanges{
            try? moc.save()
        }
    }

hope this helps, DMG

*** added as an afterthought: this code works well if the IndexSet has only one entry. if there are situations where you have more than one entry, this may or may not do the right thing (depending on the order of entries in the IndexSet).

it might be safer to explicitly delete in reverse order of index so that deletions don't conflict with the indexing of the computed property candyArray. so you might want the deletion loop above to be written using

for offset in offsets.sorted().reversed() {

DMG

7      

Dear DMG - Thank you very much for the clear and detailed explanation, it works perfectly! I messed around with this for hours, cannot believe I did not think of using a closure. Its swift after all!! Thanks again!

3      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

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.