我正在使用嵌套上下文模式來支持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