对于coredata中的并发性我使用父子MOC概念,其中父上下文为NSMainQueueConcurrencyType
,子上下文为NSPrivateQueueConcurrencyType
,下面是代码
- (NSManagedObjectContext *)managedObjectContext
{
if (managedObjectContext != nil) {
return managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];// DONE to avoid crash when the app auto logs out
managedObjectContext.persistentStoreCoordinator = coordinator;
}
return managedObjectContext;
}
-(NSManagedObjectContext *)getPrivateMOC
{
NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[private setParentContext:[self managedObjectContext]];
return private;
}
-(void)storeCustomerData:(NSArray *)custData
{
NSManagedObjectContext *currentbgContext = [self getPrivateMOC];
[currentbgContext performBlock:^{
for (NSDictionary *jsonObject in custData) {
CustomerEntity *custEntity = [NSEntityDescription insertNewObjectForEntityForName:@"CustomerEntity" inManagedObjectContext:currentbgContext];
custEntity.fname = [jsonObject field:@"fname"];
custEntity.lname = [jsonObject field:@"lname"];
}
NSError *error = nil;
if (![currentbgContext save:&error]) {
NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
//abort();
}
}];
}
如果我在方法storeCustomerData
中使用父上下文,它可以工作,但使用子上下文getPrivateMOC()
则不行。
如果我遗失任何内容,请告诉我
答案 0 :(得分:0)
I guess I understood your problem, Please try the below code
// Used to propegate saves to the persistent store (disk) without blocking the UI
- (NSManagedObjectContext *)masterManagedObjectContext {
if (_masterManagedObjectContext != nil) {
return _masterManagedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_masterManagedObjectContext.retainsRegisteredObjects = YES; //TO-DO : Need update this later
[_masterManagedObjectContext performBlockAndWait:^{
[_masterManagedObjectContext setPersistentStoreCoordinator:coordinator];
// [_masterManagedObjectContext setUndoManager:nil];
}];
}
return _masterManagedObjectContext;
}
// Return the NSManagedObjectContext to be used in the background during sync
- (NSManagedObjectContext *)backgroundManagedObjectContext {
if (_backgroundManagedObjectContext != nil) {
return _backgroundManagedObjectContext;
}
NSManagedObjectContext *masterContext = [self masterManagedObjectContext];
if (masterContext != nil) {
_backgroundManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_backgroundManagedObjectContext performBlockAndWait:^{
[_backgroundManagedObjectContext setParentContext:masterContext];
}];
}
return _backgroundManagedObjectContext;
}
// Return the NSManagedObjectContext to be used in the background during sync
- (NSManagedObjectContext *)newManagedObjectContext {
NSManagedObjectContext *newContext = nil;
NSManagedObjectContext *masterContext = [self masterManagedObjectContext];
if (masterContext != nil) {
newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[newContext performBlockAndWait:^{
[newContext setParentContext:masterContext];
}];
}
return newContext;
}
- (void)saveMasterContext {
[self.masterManagedObjectContext performBlockAndWait:^{
NSError *error = nil;
BOOL saved = [self.masterManagedObjectContext save:&error];
if (!saved) {
// do some real error handling
//NSLog(@"Could not save master context due to %@", error);
}
}];
}
- (void)saveBackgroundContext {
[self.backgroundManagedObjectContext performBlockAndWait:^{
NSError *error = nil;
BOOL saved = [self.backgroundManagedObjectContext save:&error];
if (!saved) {
// do some real error handling
//NSLog(@"Could not save background context due to %@", error);
}
}];
}
static dispatch_queue_t coredata_background_save_queue;
dispatch_queue_t background_save_queue()
{
if (coredata_background_save_queue == NULL)
{
coredata_background_save_queue = dispatch_queue_create("com.magicalpanda.coredata.backgroundsaves", 0);
}
return coredata_background_save_queue;
}
- (void)saveDataInBackgroundWithContext:(void(^)(NSManagedObjectContext *context))saveBlock
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[self saveDataInContext:saveBlock];
});
}
- (void)saveDataInContext:(void(^)(NSManagedObjectContext *context))saveBlock
{
NSManagedObjectContext *context = [[EFCoreDataController sharedInstance] backgroundManagedObjectContext];
[context setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[[self objectContext] setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
// [[self objectContext] observeContext:context]; //step 3
// block(context); //step 4
if ([context hasChanges]) //step 5
{
NSError *e;
[[self objectContext] save:&e]; //MagicalRecord will dump errors to the console with this save method
}
}