FetchRequest с NSPredicate не обновляет новые записи - PullRequest
1 голос
/ 02 мая 2020

Я экспериментирую с SwiftUI и CoreData. В ListView я показываю все записи с данным предикатом через FetchRequest:

struct MyList: View {
    var task: Task

    @FetchRequest
    var events: FetchedResults<Event>

    @Environment(\.managedObjectContext)
    var viewContext

    init(task: Task) {
        self.task = task
        self._events = FetchRequest(entity: Event.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Event.timestamp, ascending: true)],
                                    predicate: NSPredicate(format: "%K == %@", #keyPath(Event.task), task.id.uuidString), animation: .default)
    }

    var body: some View {
        VStack {
            EditButton()
            List {
                ForEach(self.events, id: \.self) { event in
                    Text("\(event.someProperty)")
                }
            }.onDelete { indices in
                self.events.delete(at: indices, from: self.viewContext)
            }
        }
        .navigationBarItems(
             trailing: Button(
                 action: {
                     withAnimation {
                         Event.create(for: self.task, in: self.viewContext)
                     }
                 }
              ) {
                  Image(systemName: "plus")
              }
        )
    }
}

extension Event {
    static func create(for task: Task, in managedObjectContext: NSManagedObjectContext){
        let newEvent = self.init(context: managedObjectContext)
        newEvent.task = task.id
        newEvent.timestamp = Date()

        do {
            try  managedObjectContext.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }   
}

extension Collection where Element == Event, Index == Int {
    func delete(at indices: IndexSet, from managedObjectContext: NSManagedObjectContext) {
        indices.forEach { managedObjectContext.delete(self[$0]) }       

        do {
            try managedObjectContext.save()
        } catch {
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}

Все работает, если хорошо. Если я удаляю запись, она автоматически удаляется из списка.

Но если я добавляю запись, она добавляется в список только после перезапуска приложения. Если я удаляю NSPredicate новые записи отображаются сразу. Это ошибка или я что-то упустил? Спасибо за вашу помощь.

1 Ответ

1 голос
/ 04 мая 2020

Имеет pbasdf указал, что проблема действительно в сравнении UUID в NSPredicate. После сравнения UUID вместо строк все работает как положено.

Сравнение UUID с заданной строкой приводит к получению исходных данных. Вероятно, он был правильно обработан в базе данных, но не для обработки «в памяти». Например,

NSPredicate(format: "%K == %@", #keyPath(Event.task), task.id.uuidString)

работает для операции удаления, но не для вставки новых записей.

Для решения этой проблемы предикат должен выглядеть следующим образом

NSPredicate(format: "%K == %@", #keyPath(Event.task), task.id as CVarArg)

, см. также: https://jisyed.github.io/blog/2018/using-uuids-in-predicates-to-fetch-core-data-entities/

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