我正在使用嵌套上下文模式来支持CoreData的多线程工作。 我有CoredDataManager单例类和环境的inits是:CoreData嵌套上下文:什么是保存上下文的正确方法?
self.masterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
self.masterContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
self.mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
self.mainContext.parentContext = self.masterContext;
有关从Web服务响应我用我的CoreDataManager的API来获取新的管理范围内每个插入操作:
- (NSManagedObjectContext *)newManagedObjectContext {
NSManagedObjectContext *workerContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
workerContext.parentContext = self.mainContext;
return workerContext;
}
它看起来像(PlayerView类是NSManagedObject类的子类):
[PlayerView insertIfNeededByUniqueKey:@"playerViewId" value:playerViewId inBackgroundWithCompletionBlock:^(NSManagedObjectContext *context, PlayerView *playerView) {
playerView.playerViewId = playerViewId;
playerView.username = playerViewDictionary[@"name"];
[context saveContextWithCompletionBlock:^{
//do something
} onMainThread:NO];//block invocation on background thread
}];
saveContextWithCompletionBlock方法实现我ñ的NSManagedObjectContext类别:
- (void)saveContextWithCompletionBlock:(SaveContextBlock)completionBlock onMainThread:(BOOL)onMainThread {
__block NSError *error = nil;
if (self.hasChanges) {
[self performBlock:^{
[self save:&error];
if (error) {
@throw [NSException exceptionWithName:NSUndefinedKeyException
reason:[NSString stringWithFormat:@"Context saving error: %@\n%@\n%@", error.domain, error.description, error.userInfo]
userInfo:error.userInfo];
}
if (completionBlock) {
if (onMainThread && [NSThread isMainThread]) {
completionBlock();
} else if (onMainThread) {
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock();
});
} else if ([NSThread isMainThread]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{
completionBlock();
});
} else {
completionBlock();
}
}
}];
}
}
然后在某个阶段,我打电话CoreDataManager的方法来保存主上下文:
- (void)saveMasterContext; {
__block NSError *error;
[self.mainContext performBlock:^{
[self.mainContext save:&error];
[self treatError:error];
[self.masterContext performBlock:^{
[self.masterContext save:&error];
[self treatError:error];
}];
}];
}
我有两大类,NSManagedObject的子类 - PlayerView和邮政业。 PlayerView与Post的关系非常多。 PlayerView已保存并确定。邮政从来没有保存,我得到的错误:
CoreData:错误:从它的上下文中删除后,管理对象0x17dadd80(0x17daf930)的变化。
我认为,问题是在上下文中保存逻辑。
有一个问题是否会执行?否则if([NSThread isMainThread])dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0ul),^ { completionBlock(); });如果生成的线程与PlayerView的回调所在的线程不同,传入的上下文将不会在正确的线程上,如果您引用它而不是//执行某些操作。 – mitrenegade