2

我正在编写 iOS 6.1 并学习如何使用 Core Data。

fetchedObjects 的文档说:

“结果数组反映了控制器托管对象上下文中托管对象的内存状态,而不是它们在持久存储中的状态。但是,返回的数组不会随着托管对象的插入、修改或删除而更新。”

最后一句话与我所看到的有关。

即,我从实体中获取数据,对获取的对象(fetchedObjects.count)进行计数,然后得到我期望的结果。

然后我创建一个新对象并保存它,然后我再次执行 fetchedObjects.count 并获得与上次相同的结果 - 没有像我预期的那样增加一个。

所以,我的问题是如何在保存上下文后更新 fetchedObjects。

我在这里阅读了有关使用 NSFetchedResultsControllerDelegate 的信息,并尝试了一些建议,即我使用委托。

我指定自己为代表。

 frc.delegate = self;

我像这样添加了委托:

@interface DB : NSObject <NSFetchedResultsControllerDelegate>

我像这样实现了委托回调:

- (void) controllerDidChangeContent: (NSFetchedResultsController *) controller
    {
    ;
    }

这一切都奏效了。但我不明白为什么。

如果我删除上面的三位委托代码,当我创建一个新对象、保存我的上下文然后执行 fetchedObjects.count 时,我的代码将失败。它因计数不足而失败。

如果我添加回 NSFetchedResultsControllerDelegate 和 frc.delegate = self; 位并省略回调例程,它仍然失败。

只有当我还添加回调例程(顺便说一句,它没有任何功能)时,我的代码才会成功。

这让我有点偏执——就像想知道如果回调什么都不做,为什么它会起作用,如果这会在 99% 的时间内起作用,然后在蓝月亮中失败一次?

因此,我创建了一个布尔值并将其设置在回调例程中,因此我的代码在看到布尔值翻转之前不会执行保存后计数。但是,我认为这可能是多余的——甚至可能是愚蠢的。

oldCount = frc.fetchedObjects.count;
<create a new object here>
frcDelegateCalled = FALSE;   
[self saveDB];   
[frc.managedObjectContext processPendingChanges];   
while ( frcDelegateCalled == FALSE );   
newCount = frc.fetchedObjects.count;

- (void) controllerDidChangeContent: (NSFetchedResultsController *) controller
   {
   frcDelegateCalled = TRUE;
   }

因此,processPendingChanges 调用显然加快了更新,我的布尔值确保回调已被调用,表明在我重新计算之前 fetchedObjects 已更新。

我有点困惑为什么代码工作仅仅是因为存在回调。任何人都可以在这里阐明一下吗?

4

1 回答 1

3

只有有权访问内部的人才能确定回答,但这是我的猜测。

NSFetchedResultsController 通过侦听 来工作NSManagedObjectContextObjectsDidChangeNotification,它被发送了很多。作为优化,如果获取结果控制器没有委托,或者委托没有实现部分或全部方法,则获取的结果控制器可能不响应通知。

正如 MartinR 所提到的,这实际上是在文档中说明的,您所看到的是预期的行为:

重要提示:委托必须至少实现一种变更跟踪委托方法才能启用变更跟踪。提供 controllerDidChangeContent: 的空实现就足够了。

如果您想知道 fetch 的结果何时发生变化,FRC 委托方法就是您应该做的地方。

于 2013-09-08T18:31:01.687 回答