是否可以从 NSFetchedResultsController 获取最新的快照
Is it possible to source an up-to-date snapshot from an NSFetchedResultsController
从 iOS 13 开始,保持 UITableView
与 NSFetchedResultsController
同步的最简单方法似乎是使用快照。
只要 managedObjectContext 报告添加、删除或更新,NSFetchedResultsController 就会向其委托提供快照引用。使用快照时(NSDiffableDataSourceSnapshot
),只有一个 FRC 委托方法需要实现:controller(_:didChangeContentWith:)
。为了使该委托方法起作用,必须键入 UITableViewDiffableDataSource 和快照 <String, NSManagedObjectID>
.
有效 。
但是如果需要更新整个 table 怎么办?使用 tableView.reloadData()
或 frc.performFetch()
似乎是反模式。
编辑
我手动构建了一个快照,并在需要时调用应用。但是由于我的快照是基于 NSFetchedResultsSectionInfo 对象的,所以我似乎在复制 FRC 已经可用的内容:Hashable section titles 和 Hashable NSManagedObjectIDs
对于我之前(已删除)的回答,我深表歉意。快照与核心数据上下文无关。
NSFetchedResultsController
与 Core Data
结合使用的目的是在保存 NSManagedObjectContext
时更新 UI。
为了能够控制 diffable 数据源的动画(以解决荒谬的行为),您必须继承 UITableViewDiffableDataSource
并添加 属性 animatingDifferences
。进一步在子类中采用NSFetchedResultsControllerDelegate
(在视图控制器中采用而不是)。
class DiffableCoreDataSource: UITableViewDiffableDataSource<String,NSManagedObjectID> {
var animatingDifferences = false
}
extension DiffableCoreDataSource : NSFetchedResultsControllerDelegate
{
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
apply(snapshot as NSDiffableDataSourceSnapshot<String, NSManagedObjectID>, animatingDifferences: animatingDifferences)
animatingDifferences = true // set it to the default
}
}
在视图控制器中,将 FRC 的 delegate
设置为子类,假设有一个 dataSource
属性 表示 DiffableCoreDataSource
frc.delegate = dataSource
如果更新记录,请在保存上下文之前将 dataSource.animatingDifferences
设置为 false
。
重新加载整个 table 视图调用 frc.performFetch()
。切勿在 table 视图上调用 reloadData()
。
TL;DR:尽管 NSFetchedResultsController 能够在 managedObjectContext 报告添加、删除和更新时为其委托提供最新的快照引用,但不可能(至少目前)以编程方式直接从 FRC 访问快照。
正如 vadian 上面所建议的,使用 FRC 实例方法 performFetch()
将最新的快照应用到 DiffableData-backed UITableview
中的所有单元格。这是一种未记录的快照管理方法。但它允许单独使用 FRC 提供的快照,而不必编写独立的快照。更少的代码,以及用于快照更新的 'single-source-of-truth'。
根据其他人的反馈,缺点是 apply(_: animatingDifferences:)
方法中的 animatingDifferences
参数如果设置为 true 会触发错误。两个可重现的错误是 table 在第一次应用快照时根本无法加载。如果尝试使用 trailingSwipeActionsConfigurationForRowAt
方法或其他方法删除记录,另一个错误是应用程序崩溃。因此,使用这种后门方法的唯一方法是在所有情况下都将该 bool 设置为 false。这意味着,嗯,没有动画。
从 iOS 13 开始,保持 UITableView
与 NSFetchedResultsController
同步的最简单方法似乎是使用快照。
只要 managedObjectContext 报告添加、删除或更新,NSFetchedResultsController 就会向其委托提供快照引用。使用快照时(NSDiffableDataSourceSnapshot
),只有一个 FRC 委托方法需要实现:controller(_:didChangeContentWith:)
。为了使该委托方法起作用,必须键入 UITableViewDiffableDataSource 和快照 <String, NSManagedObjectID>
.
有效
但是如果需要更新整个 table 怎么办?使用 tableView.reloadData()
或 frc.performFetch()
似乎是反模式。
编辑
我手动构建了一个快照,并在需要时调用应用。但是由于我的快照是基于 NSFetchedResultsSectionInfo 对象的,所以我似乎在复制 FRC 已经可用的内容:Hashable section titles 和 Hashable NSManagedObjectIDs
对于我之前(已删除)的回答,我深表歉意。快照与核心数据上下文无关。
NSFetchedResultsController
与 Core Data
结合使用的目的是在保存 NSManagedObjectContext
时更新 UI。
为了能够控制 diffable 数据源的动画(以解决荒谬的行为),您必须继承 UITableViewDiffableDataSource
并添加 属性 animatingDifferences
。进一步在子类中采用NSFetchedResultsControllerDelegate
(在视图控制器中采用而不是)。
class DiffableCoreDataSource: UITableViewDiffableDataSource<String,NSManagedObjectID> {
var animatingDifferences = false
}
extension DiffableCoreDataSource : NSFetchedResultsControllerDelegate
{
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChangeContentWith snapshot: NSDiffableDataSourceSnapshotReference) {
apply(snapshot as NSDiffableDataSourceSnapshot<String, NSManagedObjectID>, animatingDifferences: animatingDifferences)
animatingDifferences = true // set it to the default
}
}
在视图控制器中,将 FRC 的 delegate
设置为子类,假设有一个 dataSource
属性 表示 DiffableCoreDataSource
frc.delegate = dataSource
如果更新记录,请在保存上下文之前将 dataSource.animatingDifferences
设置为 false
。
重新加载整个 table 视图调用 frc.performFetch()
。切勿在 table 视图上调用 reloadData()
。
TL;DR:尽管 NSFetchedResultsController 能够在 managedObjectContext 报告添加、删除和更新时为其委托提供最新的快照引用,但不可能(至少目前)以编程方式直接从 FRC 访问快照。
正如 vadian 上面所建议的,使用 FRC 实例方法 performFetch()
将最新的快照应用到 DiffableData-backed UITableview
中的所有单元格。这是一种未记录的快照管理方法。但它允许单独使用 FRC 提供的快照,而不必编写独立的快照。更少的代码,以及用于快照更新的 'single-source-of-truth'。
根据其他人的反馈,缺点是 apply(_: animatingDifferences:)
方法中的 animatingDifferences
参数如果设置为 true 会触发错误。两个可重现的错误是 table 在第一次应用快照时根本无法加载。如果尝试使用 trailingSwipeActionsConfigurationForRowAt
方法或其他方法删除记录,另一个错误是应用程序崩溃。因此,使用这种后门方法的唯一方法是在所有情况下都将该 bool 设置为 false。这意味着,嗯,没有动画。