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

Posted

技术标签:

【中文标题】在子上下文中保存核心数据不起作用【英文标题】:Core data saving on child context not working 【发布时间】:2016-06-28 11:22:50 【问题描述】:

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

如果我遗漏了什么,请告诉我

【问题讨论】:

查看这个答案***.com/questions/12271464/… 【参考方案1】:

我想我明白你的问题了,请试试下面的代码

// 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
 

【讨论】:

以上是关于在子上下文中保存核心数据不起作用的主要内容,如果未能解决你的问题,请参考以下文章

核心数据:后台更新 NSManagedObjectContext 在保存时不起作用

核心数据保存到数据库不起作用

从核心数据中检索 UUID 并设置 UUID 变量不起作用

NSFetchRequest 的 NSSortDescriptor 在上下文保存后不起作用

cdkDragHandle 在子组件中不起作用

指令在子模块中不起作用