NSFetchedResultsController не обновляет счетчик после удаления - PullRequest
0 голосов
/ 24 марта 2019

Я изучаю CoreData на Mac OS. У меня есть демонстрационная программа, которая в основном работает, за исключением того, что когда я удаляю строку из моего tableView,

fetchedResultsController.fetchedObjects?.count

не обновился.

Соответствующие свойства определены следующим образом

    var container: NSPersistentContainer!
    var fetchedResultsController: NSFetchedResultsController<Commit>!
    var count: Int { get {
        if fetchedResultsController == nil { return 0 }
        return fetchedResultsController.fetchedObjects?.count ?? 0
        } }

Метод удаления:

    func remove(itemAt index: Int) {
        guard let n = fetchedResultsController.fetchedObjects?.count,
            index < n && index >= 0,
            let commit = fetchedResultsController.fetchedObjects?[index] else { return }
        container.viewContext.delete(commit)
        saveContext()
        ddt("remove \(count)", caller: self)
    }

Количество после удаления не было обновлено, однако постоянное хранилище является правильным. Если я удаляю другую строку, она все равно не обновляется, но если я изменяю предикат (даже на предикат nil), он обновляется должным образом.

При повторном запуске все обновляется.

Мой делегат ничего не делает. Таблица обновляется в своем делегате:

    func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] {
        // left swipe
        if edge == .trailing {
            let deleteAction = NSTableViewRowAction(style: .destructive, title: "Delete", handler: {
                [unowned self] (rowAction, row) in
                    self.dataContainer.remove(itemAt: row)
                    tableView.removeRows(at: [row], withAnimation: .slideLeft)
            })
            deleteAction.backgroundColor = NSColor.red
            return [deleteAction]
        }
        // Anything other than left does nothing
        return []
    }

Что я пропустил?

(ДДТ, для тех, кто слишком молод, чтобы помнить, был инсектицидом, запрещенным много лет назад, потому что он имел тенденцию распространяться по пищевой цепи, убивая птиц, среди других видов. Я думаю, что безопасно использовать на жуках в Свифте.)

1 Ответ

2 голосов
/ 24 марта 2019
  • Прежде всего объявите fetchedResultsController как ленивое необязательное свойство и установите делегата в закрытии

    lazy var fetchedResultsController: NSFetchedResultsController<Commit> = {
    
        ...
    
        let controller = NSFetchedResultsController( ...
        controller.delegate = self
    
        ...
        return controller
    }()
    
  • Принять NSFetchedResultsControllerDelegate и реализовать методы делегата

    • func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
    • func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
    • func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>)
  • Чтобы удалить запись в NSTableViewRowAction, получите элемент в indexPath и удалите запись в стеке основных данных.Вам не нужно проверять индекс, строка действительно существует

    let indexPath = IndexPath(item: row, section: 0)
    let commit = fetchedResultsController.object(at: indexPath)
    container.viewContext.delete(commit)
    saveContext()
    

    Методы NSFetchedResultsControllerDelegate управляют обновлением пользовательского интерфейса

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