带有谓词的 NSFetchedResultsController 会忽略从不同 NSManagedObjectContext 合并的更改

发布于 2024-09-26 22:57:27 字数 838 浏览 6 评论 0原文

我使用 NSFetchedResultsController 呈现表视图内容,它有一个谓词:

[NSPredicate predicateWithFormat:@"visible == %@", [NSNumber numberWithBool:YES]]

在使用单独的 NSManagedObjectContext 的后台线程上,我更新了一些实体并更改了它们的 visible值从 NOYES。保存并合并主线程的 NSManagedObjectContext 中的更改。但是 NSFetchedResultsController 的 fetchedObjects 并没有改变。此外,控制器不会在委托上调用 -controller:didChangeObject:... 。如果实体以相同的方式在主线程上更新(我的测试应用程序调用相同的方法),则一切都会按预期进行。

此外,Notification 的 NSUpdatedObjectsKey 也包含这些对象。

目前我找到的唯一解决方案是调用每个 NSUpdatedObjectsKey 实体:

NSManagedObjectContext *context = ... // main thread context
[context existingObjectWithID:[object objectID] error:nil]

此问题仅适用于之前与谓词不匹配的更新对象。

我错过了一些明显的东西吗?

I am presenting table view contents using NSFetchedResultsController which has a predicate:

[NSPredicate predicateWithFormat:@"visible == %@", [NSNumber numberWithBool:YES]]

On background thread using separate NSManagedObjectContext I update few of the entities and change theirs visible value from NO to YES. Save, merge changes in main thread's NSManagedObjectContext. But NSFetchedResultsController's fetchedObjects doesn't change. Also controller doesn't call -controller:didChangeObject:... on delegate. If entities are updated on main thread in identical manner (my test app calls the same method), everything works as expected.

Also Notification's NSUpdatedObjectsKey contains those objects.

Currently the only solutions I've found is to call for each of NSUpdatedObjectsKey entities:

NSManagedObjectContext *context = ... // main thread context
[context existingObjectWithID:[object objectID] error:nil]

This issue is only with updated objects which previously didn't match the predicate.

Am I missing something obvious?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

若水般的淡然安静女子 2024-10-03 22:57:27

结果主 NSManagedObjectContext 没有为更新的对象触发 NSManagedObjectContextObjectsDidChangeNotification 事件,因为它没有为错误的对象执行。

通用修复(或跟踪需要此处理的对象 ID):

NSManagedObjectContext *context = [self managedObjectContext];
for(NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) {
  [[context objectWithID:[object objectID]] willAccessValueForKey:nil];
}

[context mergeChangesFromContextDidSaveNotification:notification];

来自 NSManagedObject 类参考

您可以使用以下命令调用此方法
键值为 nil 以确保
故障已被触发,如图所示
通过以下示例。

Turns out main NSManagedObjectContext didn' t event fire NSManagedObjectContextObjectsDidChangeNotification for updated objects because it is not done for faulted objects.

Generic fix (or keep a track of object IDs that needs this treatment):

NSManagedObjectContext *context = [self managedObjectContext];
for(NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) {
  [[context objectWithID:[object objectID]] willAccessValueForKey:nil];
}

[context mergeChangesFromContextDidSaveNotification:notification];

From NSManagedObject Class Reference:

You can invoke this method with the
key value of nil to ensure that a
fault has been fired, as illustrated
by the following example.

你的往事 2024-10-03 22:57:27

合并来自其他 NSManagedObjectContext 的更改后,您必须在 Background-NSManagedObjectContext 上调用 processPendingChanges 。

请参阅 CoreData 编程指南:

请注意,更改通知是在 NSManagedObjectContext 中发送的
processPendingChanges 方法。主线程与事件相关联
应用程序循环以便调用 processPendingChanges
在主程序拥有的上下文中的每个用户事件之后自动执行
线。对于后台线程来说,情况并非如此——当该方法是
调用取决于平台和发行版本,因此您
不应依赖于特定的时间。如果次要上下文不是
在主线程上,您应该自己调用 processPendingChanges
适当的时机。

You have to call processPendingChanges on your Background-NSManagedObjectContext after you merged the changes from an other NSManagedObjectContext.

See CoreData Programming Guide:

Note that the change notification is sent in NSManagedObjectContext’s
processPendingChanges method. The main thread is tied into the event
cycle for the application so that processPendingChanges is invoked
automatically after every user event on contexts owned by the main
thread. This is not the case for background threads—when the method is
invoked depends on both the platform and the release version, so you
should not rely on particular timing. If the secondary context is not
on the main thread, you should call processPendingChanges yourself at
appropriate junctures.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文