保存子上下文的核心数据不起作用

时间:2016-06-28 11:22:50

标签: ios core-data concurrency

对于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()则不行。

如果我遗失任何内容,请告诉我

1 个答案:

答案 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
 }
}