Multi Context CoreData with Threads

2019-02-20 02:09发布

问题:


UPDATE : I suppose the issue is that the parent context is not updated when the child context is saved. Still, need help.


I have tried many examples of Multi-context (Parent-Child) Core Data.

Previously my app was using the traditional way of storing data, i.e. I used an OperationQueue where I fetch the data from the server and save to the DB using a MOC and on saving fire a notification to the mainMOC to mergeChanges : NSManagedObjectContextDidSaveNotification.

Without disturbing the flow of the app, (i.e. removing the OperationQueue), I tried to implement the Parent-Child ManagedObjectContext Relationship where I used a privateMOC with concurrencyType as NSPrivateQueueConcurrencyType which has a persistantStoreCoordinator, and the mainMOC with concurrenyType as NSMainQueueConcurrencyType which is a child of the privateMOC. And in the Queue I have a tempMOC with concurrencyType as NSPrivateQueueConcurrencyType which is a child of the mainMOC.

While saving, I nest the performBlock of the three MOCs as -

[tempMOC performBlock:^{
        if (![tempMOC save:&error]) {
            NSLog(@"Error : %@",error);
        }
        [mainMOC performBlock:^{
            if (![mainMOC save:&error]) {
                NSLog(@"Error : %@",error);
            }
            [privateMOC performBlock:^{
                if (![privateMOC save:&error]) {
                    NSLog(@"Error : %@",error);
                }
            }];
        }];
    }];

I am getting Errors like CoreData 1560 and 1570 while the mainMOC is trying to save. NSValidationErrorKeyerror where it says some value is nil. Is it that the changes of the tempMOC are not going to the mainMOC ? I did not dig in but as far as I know, it should not be nil. What could possibly be the error? Please Help.

UPDATE : I tried to print the objects of tempMOC and I see proper values like :

<Element_Name: 0xc0b59c0> (entity: Element_Name; id: 0xc07ca90 <x-coredata:///Element_Name/t2DCD57A8-4C1A-4AF7-A10E-5B9603E2BB8730> ; data: {
    tag1 = nil;
    tag2 = 3430065;
    tag3 = 600;
    tag4 = N;
    tag5 = "2013-10-29 00:00:00 +0000";
    tag6 = nil;
    tag7 = 327842701;
    relation = "0xbf1f760 <x-coredata://87C54A94-701E-4108-826E-4D98A53380F9/Relation/p1>";
    tag8 = "Some_Value";

I tried to print the objects of mainMOC and I see nil value instead of the data like :

<Element_Name: 0xbd47a50> (entity: Element_name; id: 0xc0b14b0 <x-coredata:///Element_Name/t2DCD57A8-4C1A-4AF7-A10E-5B9603E2BB8740> ; data: {
    tag1 = nil;
    tag2 = nil;
    tag3 = 0;
    tag4 = nil;
    tag5 = nil;
    tag6 = nil;
    tag7 = nil;
    relation = "0xbd586c0 <x-coredata://87C54A94-701E-4108-826E-4D98A53380F9/relation/p1>";
    tag8 = nil;

回答1:

I just hit the same problem and found a solution. Without the rest of your code I cannot assure this would solve your problem, but it did solve mine.

I was instantiating some NSManagedObject classes, modifying some of their properties and THEN inserting them in the temp or child NSManagedObjectContext. All the properties were showing just fine like in your case.

But when I saved that context and the changes got pushed to the parent NSManagedObjectContext, all properties were nullified (like in your case).

I have not observersed this behaviour when using only one NSManagedObjectContext, and I have not experimented with the older NSManagedObjectContextDidSaveNotification pattern.

The solution is of course to add the NSManagedObject to a context just after initialisation, and before any property assignments are done.



回答2:

vshall,

If you already have a background insertion MOC pattern working, why are you trying to move to a parent-child MOC situation? It isn't faster. And, judging from what I can see about your implementation, you end up blocking the main thread.

There are many good reasons to use the parent-child MOC relationship. Most of them involve creating scratch or read-only MOCs. The second big use case is to have your main MOC be a child of a private concurrent MOC. That way saves are "fast" and done on the background thread. Background insertion into a child concurrent MOC of the main MOC, in my experience, is slower and causes the UI to stutter.

In answer to your question, you are trying to access items before your embedded set of saves has finished. Hence, your data is corrupt and you get exceptions.

Andrew