更改NSManagedObject属性的值不会反映在DiffableDataSource上

时间:2020-05-11 05:41:44

标签: ios swift core-data

因此,我正在使用(iOS13)(XCode 13.1)UICollectionViewDiffableDataSourceUITableViewDiffableDataSource。每当我在CoreData的{​​{1}}之一中更改属性时,DiffableAPI都不会捕获该属性,而是会自动进行更改和响应。我怀疑这是因为ManagedObject在执行isEqual操作时没有考虑属性。我也不能覆盖ManagedObject的isEqual函数。我该如何解决?

1 个答案:

答案 0 :(得分:0)

更新

找到了新的解决方案。在再次从WWDC 2019看了Making App with Core Data之后,看来在处理核心数据时我们应该在NSDiffableDataSourceSnapshotReference上使用NSDiffableDataSourceSnapshot<S,I>

let dataSourceReference = UICollectionViewDiffableDataSourceReference(collectionView: collectionView) { collectionView, indexPath, anyObjectID in
  guard 
    let objectID = anyObjectID as? NSManagedObjectID,
    let <#myObject#> = managedObjectContext.object(with: objectID) as? <#MyObject#>
  else { return nil }

  /* dequeue, configure and return cell object here */
}

collectionView.dataSource = dataSourceReference

然后,在内容更改时应用快照:

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
  dataSourceReference.applySnapshot(snapshot, animatingDifferences: true)
}

要手动创建和应用快照,请执行以下操作:

func applySnapshot(animated: Bool) {
  let ids = fetchedResultsController.fetchedObjects?.compactMap { $0.objectID as Any } ?? []
  let snapshot = NSDiffableDataSourceSnapshotReference()
  snapshot.appendSections(withIdentifiers: [<#someSection#>])
  snapshot.appendItems(withIdentifiers: ids, intoSectionWithIdentifier: <#someSection#>)
  
  dataSourceReference.applySnapshot(snapshot, animatingDifferences: animated)
}

这样做,一切都按预期工作,包括更改对象属性时。


我遇到了同样的问题。就我而言,我正在使用NSFetchedResultsController来接收模型更改。

我的解决方法是将controller(_:didChangeContentWith:)替换为

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>,
          didChange anObject: Any,
                at indexPath: IndexPath?,
                    for type: NSFetchedResultsChangeType,
                newIndexPath: IndexPath?
) {
  if type == .update {
    // apply snapshot without animation
  } else {
    // apply snapshot with animation
  }
}

相应地应用新快照。

另一种解决方法是,您不必:每次申请时都创建新快照,

  • 首先创建一个新快照并将其应用于数据源
  • 收到模型更新后,向数据源询问现有快照并通过计算差异对其进行修改,然后将其应用于数据源

这也可以解决此问题,但需要做更多的工作。

我最终使用了前一个。