为什么controllerDidChangeContent /如何工作?

时间:2013-09-08 16:29:33

标签: ios core-data delegates

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

fetchedObjects的文档说:

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

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

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

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

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

我读到了使用NSFetchedResultsControllerDelegate here并尝试了一些建议,即我使用了委托。

我指定自己为代表。

 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。

我有点困惑为什么代码只是因为回调存在而起作用。有人能在这里说清楚吗?

1 个答案:

答案 0 :(得分:3)

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

NSFetchedResultsController通过监听NSManagedObjectContextObjectsDidChangeNotification来工作,这会被发送很多。作为优化,如果没有委托,或者委托没有实现某些或所有方法,则获取的结果控制器可能不响应通知。

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

  

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

如果您想知道获取结果何时发生变化,那么无论如何都应该使用FRC委托方法。