NSFetchedResultsController在合并“NSManagedObjectContextDidSaveNotification”后没有显示所有结果
我有一个NSFetchedResultsController用谓词获取对象:
isTrash == NO
大多数情况下,这是按预期工作的,但是当一个对象被取消时,取出的结果控制器不会取出这个未被分离的对象。
怎么了?
发生这种情况的原因是mergeChangesFromContextDidSaveNotification:
如何处理更新的对象。 NSManagedObjectContext
保留上下文中正在使用的对象的logging,这些被称为已注册对象( NSManagedObjectContext
具有访问和有条件地获取已注册对象的方法)。 mergeChangesFromContextDidSaveNotification:
仅处理在上下文中注册的对象的更新。 这对NSFetchedResultsControllers
有一个敲门效应,解释了问题的原因。
这是如何发挥的:
-
FRC设置谓词不匹配所有对象(从而防止不匹配谓词的对象注册在FRC上下文中)。
-
第二个上下文对对象进行更改,这意味着它现在与FRC谓词相匹配。 第二个上下文被保存。
-
FRCs上下文处理
NSManagedObjectContextDidSaveNotification
但仅更新其注册对象,因此它不会更新现在与FRC谓词相匹配的对象。 -
有一个保存时,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]; } } }); }
尝试设置shouldRefreshRefetchedObjects
为NSFetchRequest
为您的获取结果控制器。
这提供了更方便的方式来确保托pipe对象属性值与商店相一致,比依次使用refreshObject:mergeChanges:(NSManagedObjetContext)来实现多个对象。
- 从asynchronousWeb服务响应更新托pipe对象的最佳方法?
- 如何确保OperationQueue中的操作一个接一个地完成
- 为什么我应该为每个新线程或NSOperation创build一个NSManagedObjectContext,而不是在主线程上调用Core Data?
- 如何找出是什么导致IOS设备上的错误崩溃报告?
- iOS核心数据何时保存上下文?
- 用于保存核心数据的NSPersistentContainer并发性
- 在UITableView上执行GCD
- Swift 3 GCDlockingvariables和block_and_release错误
- 为什么Objective-C / Swift中的asynchronousnetworkingtesting困难?