为什么/如何controllerDidChangeContent 工作?

Gal*_*mon 2 delegates core-data ios

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

\n\n

fetchedObjects 的文档说:

\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n\n

我指定自己为代表。

\n\n
 frc.delegate = self;\n
Run Code Online (Sandbox Code Playgroud)\n\n

我像这样添加了委托:

\n\n
@interface DB : NSObject <NSFetchedResultsControllerDelegate>\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
- (void) controllerDidChangeContent: (NSFetchedResultsController *) controller\n    {\n    ;\n    }\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n\n
oldCount = frc.fetchedObjects.count;\n<create a new object here>\nfrcDelegateCalled = FALSE;   \n[self saveDB];   \n[frc.managedObjectContext processPendingChanges];   \nwhile ( frcDelegateCalled == FALSE );   \nnewCount = frc.fetchedObjects.count;\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
- (void) controllerDidChangeContent: (NSFetchedResultsController *) controller\n   {\n   frcDelegateCalled = TRUE;\n   }\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,processPendingChanges 调用显然会加快更新速度,并且我的布尔值确保回调已被调用,表明 fetchedObjects 在我重新计数之前已被更新。

\n\n

我有点困惑为什么代码仅仅因为存在回调而起作用。任何人都可以在这里阐明一些情况吗?

\n

jrt*_*ton 5

只有了解内部情况的人才能肯定地回答,但这是我的猜测。

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

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

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

如果您想知道提取结果何时发生变化,那么无论如何您都应该在 FRC 委托方法中执行此操作。