NSFetchedResultsController在合并“NSManagedObjectContextDidSaveNotification”后没有显示所有结果

我有一个NSFetchedResultsController用谓词获取对象:

isTrash == NO

大多数情况下,这是按预期工作的,但是当一个对象被取消时,取出的结果控制器不会取出这个未被分离的对象。

怎么了?

发生这种情况的原因是mergeChangesFromContextDidSaveNotification:如何处理更新的对象。 NSManagedObjectContext保留上下文中正在使用的对象的logging,这些被称为已注册对象( NSManagedObjectContext具有访问和有条件地获取已注册对象的方法)。 mergeChangesFromContextDidSaveNotification:仅处理在上下文中注册的对象的更新。 这对NSFetchedResultsControllers有一个敲门效应,解释了问题的原因。

这是如何发挥的:

  1. FRC设置谓词不匹配所有对象(从而防止不匹配谓词的对象注册在FRC上下文中)。

  2. 第二个上下文对对象进行更改,这意味着它现在与FRC谓词相匹配。 第二个上下文被保存。

  3. FRCs上下文处理NSManagedObjectContextDidSaveNotification但仅更新其注册对象,因此它不会更新现在与FRC谓词相匹配的对象。

  4. 有一个保存时,FRC不会执行另一个提取,因此不知道应该包含更新的对象。

修复

解决scheme是在合并通知时获取所有更新的对象。 以下是一个合并方法示例:

 -(void)mergeChanges:(NSNotification *)notification { dispatch_async(dispatch_get_main_queue, ^{ NSManagedObjectContext *savedContext = [notification object]; NSManagedObjectContext *mainContext = self.managedObjectContext; BOOL isSelfSave = (savedContext == mainContext); BOOL isSamePersistentStore = (savedContext.persistentStoreCoordinator == mainContext.persistentStoreCoordinator); if (isSelfSave || !isSamePersistentStore) { return; } [mainContext mergeChangesFromContextDidSaveNotification:notification]; //BUG FIX: When the notification is merged it only updates objects which are already registered in the context. //If the predicate for a NSFetchedResultsController matches an updated object but the object is not registered //in the FRC's context then the FRC will fail to include the updated object. The fix is to force all updated //objects to be refreshed in the context thus making them available to the FRC. //Note that we have to be very careful about which methods we call on the managed objects in the notifications userInfo. for (NSManagedObject *unsafeManagedObject in notification.userInfo[NSUpdatedObjectsKey]) { //Force the refresh of updated objects which may not have been registered in this context. NSManagedObject *manangedObject = [mainContext existingObjectWithID:unsafeManagedObject.objectID error:NULL]; if (manangedObject != nil) { [mainContext refreshObject:manangedObject mergeChanges:YES]; } } }); } 

尝试设置shouldRefreshRefetchedObjectsNSFetchRequest为您的获取结果控制器。

这提供了更方便的方式来确保托pipe对象属性值与商店相一致,比依次使用refreshObject:mergeChanges:(NSManagedObjetContext)来实现多个对象。