SwiftUI: Как обновить список sh после сброса контекста в Core Data - PullRequest
0 голосов
/ 11 апреля 2020

Всякий раз, когда я добавляю / удаляю элементы из постоянного хранилища, список, источник которого использует результаты FetchRequest.wrappedValue, обновляется, и появляются новые записи / удаленные записи исчезают (с помощью кнопки «Добавить» / проведите пальцем по действию «Удалить»). Это происходит, даже если я не сохраняю контекст. Если я решу сделать сброс контекста после внесения этих изменений без сохранения, мое представление списка будет повреждено - удаленные записи по-прежнему пропадают, а вновь добавленные записи отображаются с неправильными значениями.

Теперь документация Swift действительно говорит о том, что несохраненные управляемые объекты «забываются» после использования reset () в NSManagedObjectContext, который все это объясняет, но мне не удалось обновить список sh. Я могу использовать идентификатор в списке для автоматического обновления sh их значений, но он не добавляет / удаляет отсутствующие записи. Есть ли способ сделать это? Попытка удалить эти «забытые» объекты после сброса контекста вызывает cra sh при следующем сохранении контекста.

Вот код, который я использовал. У меня есть только один объект API с одним атрибутом Id Int32

import SwiftUI
import CoreData

struct test: View {
    private var context: NSManagedObjectContext
    var request: FetchRequest<API>
    var results : FetchedResults<API>{request.wrappedValue}

    @State private var refreshingID = UUID()

    var body: some View {
        VStack {
            HStack {
                Button(action: {self.APICount()}) {
                    Text("API count")
                }
                Spacer()
                Button(action: {self.addNewElement()}) {
                    Text("Add")
                }
                Spacer()
                Button(action: {self.clearList()}) {
                    Text("Clear")
                }
                Spacer()
                Button(action: {self.saveContext()}) {
                    Text("Save context")
                }
            }
            Spacer().frame(height: 40)

            HStack {
                Button(action: {self.reverseChanges()}) {
                    Text("reset context")
                }
                Spacer()
                Button(action: {self.crash()}) {
                    Text("crash app")
                }
                Spacer()
                Button(action: {self.checkContext()}) {
                    Text("context has changes?")
                }
            }

            List {
                ForEach(results, id: \.self) { result in
                    Text("\(result.id)")
                }.onDelete(perform: deleteAPI)
            }.id(refreshingID)
        }
    }

    private func APICount() {
        let NSRequest = NSFetchRequest<API>(entityName: "API")
        NSRequest.sortDescriptors = [NSSortDescriptor(keyPath: \API.id, ascending: true)]
        do {
            try print("count=\(self.context.fetch(NSRequest).count)")
        } catch let error {
            fatalError(error.localizedDescription)
        }
    }

    private func reverseChanges() {
        self.context.reset()
        self.refreshingID = UUID()
    }

    private func checkContext() {
        print("checkContext has changes? \(self.context.hasChanges)")
    }

    private func crash() {
        print("before crash has changes? \(self.context.hasChanges)")
        fatalError("Crash")
    }

    private func clearList() {
        for api in results {
            self.context.delete(api)
        }
    }

    private func deleteAPI(indexes: IndexSet) {
        for index in indexes {
            self.context.delete(results[index])
        }
    }

    private func addNewElement() -> Void {
        let api = API.init(context: self.context)
        api.id = Int32(test.getNextID(from: self.context))
    }

    private func saveContext() {
        do {
            try self.context.save()
        } catch let error {
            fatalError(error.localizedDescription)
        }
    }


    public init() {
        self.context = test.getMOC()
        self.request = FetchRequest<API>(entity: API.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \API.id, ascending: true)])
    }


    // MARK: - Static functions

    static func getMOC() -> NSManagedObjectContext {
        guard let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext else {
            fatalError("Unable to read managed object context.")
        }
        return context
    }

    static func getNextID(from context: NSManagedObjectContext) -> Int {
        let request = NSFetchRequest<API>(entityName: "API")
        request.sortDescriptors = [NSSortDescriptor(keyPath: \API.id, ascending: false)]
        request.fetchLimit = 1
        do {
            return Int(try context.fetch(request).first?.id ?? 0) + 1
        } catch let error {
            fatalError(error.localizedDescription)
        }
    }
}
...