当parentMOC具有插入后跟保存时,对于父母和子MOC的情况,Apple文档不清楚(或者我找不到)。
我正在使用MARCUS ZARRA的http://martiancraft.com/blog/2015/03/core-data-stack/方法,其中privateQMOC位于顶部,childMainMOC位于主线程之一。
问题
我通过在privateMOC上调用save的后台Internet请求向privateMOC添加10,000个对象,但是在parentMainMOC上下文之后构建的任何NSFetchedResultsControllers都不会在父节省之后调用我的委托。因此,界面不会更新以显示parentMOC中的更改。
我想调用一些内容来更新childMainMOC中的所有对象 - 然后应该调用子控制器上的委托方法。
或其他一些解决方案。
答案 0 :(得分:1)
关键信息:
其余的上下文将是主队列上下文的子项
因此,处理下载数据的上下文必须是主上下文的子项,当您保存该子项然后保存主上下文时,则保存持久上下文。
当您保存数据处理上下文时,它会立即通知父主线程上下文,但您仍需要2次保存才能将数据存入磁盘。
答案 1 :(得分:1)
好的 - 所以我想出来了。
该模型如下: 马库斯·扎拉的http://martiancraft.com/blog/2015/03/core-data-stack/ privateMOC位于root,这可以提供更好的性能,并且出于其他原因也需要这种方式。我只使用2个MOC:私有根1和子主线程1。
然后读到这个: 基本上他解释了Core Data如何处理通知等。 http://benedictcohen.co.uk/blog/archives/308
然后 - 我需要做的最后一件事:确保程序中的所有objectID都是真正永久的。
- (id)insertNewObjectForEntityName:(NSString *)entityName inManagedObjectContext:(NSManagedObjectContext *)context {
NSManagedObject *object = [NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context];
// Make sure all inserted objects have a permanent ID.
// THIS IS VITAL. Without getting the permanentIDs, changes that come in from the web will not propogate to the child mainQ MOC and the UI will not update.
// Tested to be performant.
//NSLog(@"testing this - object.objectID is a temp now I think: %@ isTemp:%d", object.objectID, (int) [object.objectID isTemporaryID]);
// http://stackoverflow.com/questions/11990279/core-data-do-child-contexts-ever-get-permanent-objectids-for-newly-inserted-obj
NSError* error = nil;
[context obtainPermanentIDsForObjects:@[object] error:&error];
if (error || [object.objectID isTemporaryID])
NSLog(@"obtainPermanentIDsForObjects is NOT WORkING - FIX: a new %@ isTemp: %d !!", entityName, (int) [object.objectID isTemporaryID]);
return object;
}
此外,我需要根据Benedicts文章 - 监听父根私有MOC的更改
/// . http://benedictcohen.co.uk/blog/archives/308 good info !
/// I need this firing as sometimes objects change and the save notification below is not enough to make sure the UI updates.
- (void)privateQueueObjectContextDidChangeNotification:(NSNotification *)notification {
NSManagedObjectContext *changedContext = notification.object;
NSManagedObjectContext *childContext = self.mainQueueObjectContext;
BOOL isParentContext = childContext.parentContext == changedContext;
if (!isParentContext) return;
//Collect the objectIDs of the objects that changed
__block NSMutableSet *objectIDs = [NSMutableSet set];
[changedContext performBlockAndWait:^{
NSDictionary *userInfo = notification.userInfo;
for (NSManagedObject *changedObject in userInfo[NSUpdatedObjectsKey]) {
[objectIDs addObject:changedObject.objectID];
}
for (NSManagedObject *changedObject in userInfo[NSInsertedObjectsKey]) {
[objectIDs addObject:changedObject.objectID];
}
for (NSManagedObject *changedObject in userInfo[NSDeletedObjectsKey]) {
[objectIDs addObject:changedObject.objectID];
}
}];
//Refresh the changed objects
[childContext performBlock:^{
for (NSManagedObjectID *objectID in objectIDs) {
NSManagedObject *object = [childContext existingObjectWithID:objectID error:nil];
if (object) {
[childContext refreshObject:object mergeChanges:YES];
//NSLog(@"refreshing %@", [object description]);
}
}
}];
}
- (void)privateQueueObjectContextDidSaveNotification:(NSNotification *)notification {
//NSLog(@"private Q MOC has saved");
[self.mainQueueObjectContext performBlock:^{
[self.mainQueueObjectContext mergeChangesFromContextDidSaveNotification:notification];
// I had UI update problems which I fixed with mergeChangesFromContextDidSaveNotification along with obtainPermanentIDsForObjects: in the insertEntity call.
}];
}
/// When the MainMOC saves - the user has changed data.
/// We save up into the privateQ as well at this point.
- (void)mainQueueObjectContextDidSaveNotification:(NSNotification *)notification {
NSLog(@"main Q MOC has saved - UI level only changes only please");
[self.privateQueueObjectContext performBlock:^{
NSError* error = nil;
if (self.privateQueueObjectContext.hasChanges) {
[self.privateQueueObjectContext save:&error];
if (error)
{
NSLog(@"Save up error - the actual datastore was not updated : %@", error);
}
} else {
//NSLog(@"No need to save");
}
}];
}