SwiftUI - удаление из базовых данных NSSet - @FetchRequest с помощью .onDelete () - PullRequest
1 голос
/ 04 апреля 2020

Я прорабатываю бесплатный, общедоступный курс Hacking With Swift. К сожалению, глава «Базовые данные» не объясняет, как удалить объект в NSSet, который используется в отношении один ко многим. Я посмотрел на документацию и попытался определить, как использовать Сгенерированные средства доступа, но без особого успеха. Если кто-то сможет объяснить, как это сделать, я буду очень признателен, потому что мне больше всего интересно знать !!
Отношение один ко многим

Что я пытался сделать так далеко и не удалось !!!


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

}

Класс:

Страна расширения {

@nonobjc public class func fetchRequest() -> NSFetchRequest<Country> {
    return NSFetchRequest<Country>(entityName: "Country")
}

@NSManaged public var fullName: String?
public var wrappedFullName: String {
    fullName ?? "Unknown Full Name"
}
@NSManaged public var shortName: String?
public var wrappedShortName: String{
    shortName ?? "Unknown Short Name"

}
public var candyArray:[Candy] {
    let set = candy as? Set<Candy> ?? []
    return set.sorted {
        $0.wrappedName < $1.wrappedName
    }
}


@NSManaged public var candy: NSSet?

}

// MARK: сгенерированные средства доступа для расширения конфеты Страна {

@objc(addCandyObject:)
@NSManaged public func addToCandy(_ value: Candy)

@objc(removeCandyObject:)
@NSManaged public func removeFromCandy(_ value: Candy)

@objc(addCandy:)
@NSManaged public func addToCandy(_ values: NSSet)

@objc(removeCandy:)
@NSManaged public func removeFromCandy(_ values: NSSet)

} ​​

ContentView @Environment (.managedObjectContext) var moc @FetchRequest (entity: Country.entity () , sortDescriptors: []) различные страны: FetchedResults

var body: some View {

    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)
        }

        Button("Add") {
            let candy1 = Candy(context: self.moc)
            candy1.name = "Mars"
            candy1.origin = Country(context: self.moc)
            candy1.origin?.shortName = "UK"
            candy1.origin?.fullName = "United Kingdom"

            let candy2 = Candy(context: self.moc)
            candy2.name = "KitKat"
            candy2.origin = Country(context: self.moc)
            candy2.origin?.shortName = "UK"
            candy2.origin?.fullName = "United Kingdom"

            let candy3 = Candy(context: self.moc)
            candy3.name = "Twix"
            candy3.origin = Country(context: self.moc)
            candy3.origin?.shortName = "UK"
            candy3.origin?.fullName = "United Kingdom"

            let candy4 = Candy(context: self.moc)
            candy4.name = "Toblerone"
            candy4.origin = Country(context: self.moc)
            candy4.origin?.shortName = "CH"
            candy4.origin?.fullName = "Switzerland"

            try? self.moc.save()
        }
    }

}

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

} Интерфейс пользователя

Ответы [ 2 ]

0 голосов
/ 15 апреля 2020

В конце концов, это решение, переданное в замыкании от DMG, сработало очень хорошо:

Хорошо объясненное решение здесь.

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



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: { offsets in
                        self.deleteCandies(at: offsets, from: country)
                    })
                }
            }
        }
0 голосов
/ 13 апреля 2020

Я наткнулся на ту же проблему и решил ее с помощью функции removeFromCandy (_ value: Candy) , созданной из подкласса NSManagedObject.

    var body: some View {

        VStack {
            List {
                ForEach(countries, id: \.self) { country in
                    Section(header: Text(country.wrappedFullName)) {
                        ForEach(country.candyArray, id: \.self) { candy in
                            Text(candy.wrappedName)
                        }.onDelete {indexSet in
                            let deleteItem = self.country.candyArray[indexSet.first!]
                            self.country.removeFromCandy(deleteItem)
                            self.moc.delete(deleteItem)

                            do {
                                try self.moc.save()
                            } catch {
                                print(error)
                            }               
                        }
                    }
                }
            }

            Button("Add") {
                let candy1 = Candy(context: self.moc)
                candy1.name = "Mars"
                candy1.origin = Country(context: self.moc)
                candy1.origin?.shortName = "UK"
                candy1.origin?.fullName = "United Kingdom"

                try? self.moc.save()
            }
        }

    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...