更改 NSFetchedResultsController 的 fetchRequest.predicate 不会触发委托

Posted

技术标签:

【中文标题】更改 NSFetchedResultsController 的 fetchRequest.predicate 不会触发委托【英文标题】:Changing NSFetchedResultsController's fetchRequest.predicate does not trigger delegate 【发布时间】:2016-01-10 20:47:36 【问题描述】:

我在 FRC 的 fetchRequest 上有一个 NSPredicate。在某个时候,一个对象被添加到 CoreData,我创建了一个新谓词,更新 fetchRequest 并执行获取:

self.fetchedAddressesController.fetchRequest.predicate = self.predicate;
BOOL success = [self.fetchedAddressesController performFetch:nil];

但是,这不会调用像 controllerWillChangeContent: 这样的 FRC 委托方法。而且我的表格视图没有更新。

但是,当我添加以下行时:

[self.tableView reloadData];

在上面显示的两个下方,我确实看到了预期的更新。这说明要显示的数据确实发生了变化。

我检查了新的谓词,没问题。我还将FRC的delegate设置为self,其他情况下调用它的方法。

任何想法已经有什么问题了吗?

【问题讨论】:

【参考方案1】:

您描述的行为是预期的。根据Apple documentation,如果要修改 NSFetchedResultsController 上的获取请求,则必须删除缓存(如果您正在使用缓存),修改 NSFetchRequest,然后调用 performFetch:(不会调用任何委托方法)。

如果您想知道谓词之间发生了什么变化,您需要存储旧状态并进行比较。我过去为此使用的库是Doppelganger。

【讨论】:

我确实查阅了这个文档,但我并没有轻易发现它说没有调用委托方法。我在哪里可以找到那个?相反,我读到:'仅内存跟踪:......更新部分和订购信息......'。 参见developer.apple.com/library/ios/documentation/CoreData/…中的“修改获取请求”部分【参考方案2】:

当 FRC 观察到在您执行提取后它所关注的已提取对象集发生变化时,将调用委托方法。如果您更改谓词并进行新的提取,FRC 将被重置,现在正在观察一组不同的对象。没有调用委托方法,因为原始对象集中没有任何变化。

【讨论】:

【参考方案3】:

如果你真的要更改实体,请小心...

我们遇到了一个棘手的问题,不仅排序发生了变化,而且实际的实体类也发生了变化,因此对于两个不同的选项卡按钮,

let r = NSFetchRequest<NSFetchRequestResult>(entityName: "CD_Cats")

然后..

let r = NSFetchRequest<NSFetchRequestResult>(entityName: "CD_Dogs")

事实上,如果你这样做,这将不起作用:

func buttonLeft() 
    mode = .cats
    bringupFetchRequest()
    pull.feedForCats() // get fresh info if any at the endpoints


func buttonRight() 
    mode = .dogs
    bringupFetchRequest()
    pull.feedForDogs() // get fresh info if any at the endpoints

它最终会崩溃。

看来你需要这个:

func buttonLeft() 
    mode = .cats
    bringupFetchRequest()
    tableView.reloadData()
    pull.feedForCats() // get fresh info if any at the endpoints


func buttonRight() 
    mode = .dogs
    bringupFetchRequest()
    tableView.reloadData()
    pull.feedForDogs() // get fresh info if any at the endpoints

这(似乎)可靠地工作。

【讨论】:

以上是关于更改 NSFetchedResultsController 的 fetchRequest.predicate 不会触发委托的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 3 中难以配置 NSFetchedResultsController

如何根据计算的属性过滤来自 NSFetchedResultsController 的结果?

为啥 beginUpdates/endUpdates 会重置表视图位置以及如何阻止它这样做?

HAC 集群更改 IP(单节点更改全部节点更改)

更改fancybox iframe的大小-我可以更改宽度但不能更改高度?

在运行时更改方向更改 ViewControllers