述語でオブジェクトをフェッチする NSFetchedResultsController があります。
isTrash == NO
ほとんどの場合、これは期待どおりに機能しますが、オブジェクトが untrashed になると、fetched results コントローラーは untrashed オブジェクトをフェッチしません。
何がうまくいかないのですか?
述語でオブジェクトをフェッチする NSFetchedResultsController があります。
isTrash == NO
ほとんどの場合、これは期待どおりに機能しますが、オブジェクトが untrashed になると、fetched results コントローラーは untrashed オブジェクトをフェッチしません。
何がうまくいかないのですか?
これが発生する理由はmergeChangesFromContextDidSaveNotification:
、更新されたオブジェクトを処理する方法によるものです。NSManagedObjectContext
コンテキストで使用されているオブジェクトの記録を保持します。これらは登録済みオブジェクトと呼ばれます (登録済みオブジェクトNSManagedObjectContext
にアクセスし、条件付きで取得するためのメソッドがあります)。mergeChangesFromContextDidSaveNotification:
コンテキストに登録されているオブジェクトの更新のみを処理します。これにはNSFetchedResultsControllers
、問題の原因を説明するための影響があります。
プレイ方法は次のとおりです。
FRC は、すべてのオブジェクトに一致しない述語を使用してセットアップされます (したがって、述語に一致しないオブジェクトが FRC コンテキストに登録されるのを防ぎます)。
2 番目のコンテキストはオブジェクトに変更を加えます。これは、オブジェクトが FRC の述語に一致することを意味します。2 番目のコンテキストが保存されます。
FRC コンテキストはNSManagedObjectContextDidSaveNotification
、登録されたオブジェクトを処理しますが、更新するだけです。したがって、現在 FRC 述語に一致するオブジェクトは更新しません。
FRC は保存の際に別のフェッチを実行しないため、更新されたオブジェクトを含める必要があることを認識しません。
解決策は、通知をマージするときに更新されたすべてのオブジェクトを取得することです。マージ方法の例を次に示します。
-(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];
}
}
});
}
取得した結果のコントローラーをon に設定shouldRefreshRefetchedObjects
してみてください。YES
NSFetchRequest
これにより、複数のオブジェクトに対して refreshObject:mergeChanges: (NSManagedObjetContext) を順番に使用するよりも、マネージド オブジェクトのプロパティ値がストアと一致することを確認するためのより便利な方法が提供されます。