【问题标题】:NSFetchedResultsController doesn't update count after deleteNSFetchedResultsController 在删除后不更新计数
【发布时间】:2019-08-14 23:48:18
【问题描述】:

我在 mac os 上学习 CoreData。我有一个基本上可以工作的演示程序,除了当我从 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 []
    }

我遗漏了什么?

(对于那些太年轻的人来说,ddt 是一种多年前被禁止使用的杀虫剂,因为它往往会在食物链上传播,杀死鸟类和其他物种。我认为在 Swift 中使用它是安全的。)

【问题讨论】:

    标签: swift macos core-data


    【解决方案1】:
    • 首先将fetchedResultsController 声明为惰性非可选属性并在闭包中设置委托

      lazy var fetchedResultsController: NSFetchedResultsController<Commit> = {
      
          ...
      
          let controller = NSFetchedResultsController( ...
          controller.delegate = self
      
          ...
          return controller
      }()
      
    • 采用NSFetchedResultsControllerDelegate并实现委托方法

      • func controllerWillChangeContent(_ controller: NSFetchedResultsController&lt;NSFetchRequestResult&gt;)
      • func controller(_ controller: NSFetchedResultsController&lt;NSFetchRequestResult&gt;, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
      • func controllerDidChangeContent(_ controller: NSFetchedResultsController&lt;NSFetchRequestResult&gt;)
    • 要删除NSTableViewRowAction 中的记录,请获取 indexPath 处的项目并删除核心数据堆栈中的记录。您不需要检查索引,该行确实存在

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

      NSFetchedResultsControllerDelegate 方法管理 UI 的更新

    【讨论】:

    • 谢谢。干净多了,你帮助我更好地理解了 row/IndexPath 的东西。我想。但是......计数和section[0].numberOfObjects 仍然没有得到更新。我可以通过重新获取来强制它,所以这不是障碍,但我仍然对这种行为感到困惑。
    • 我的错。粗心的错误,没有正确连接。一切看起来都是正确的。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多