Multi Context CoreData with Threads
Asked Answered
N

2

1

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;
Nadene answered 29/10, 2013 at 18:20 Comment(0)
W
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.

Worden answered 18/12, 2013 at 0:1 Comment(0)
F
0

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

Frankie answered 30/10, 2013 at 13:23 Comment(4)
the background insertion MOC hangs the UI when the main MOC is updated via the notification-NSManagedObjectContextDidSaveNotification. After some googling, I found that the Parent-Child MOC doesn't hang the UX as compared to the traditional MOCNadene
I am not able to confirm if the code is trying to access the set before the save is getting finished as I tried to embed the save in performBlockAndWait also.Nadene
vshall, As you don't list your source as to why you think the parent-child MOC is faster and doesn't hang the UI, I cannot address your claim. In my experience, that is not the case. As to your case, I think you are trying to access data before it has been saved. You can probably test that it is so by delaying your reading code. AndrewFrankie
adonoho, here are some links : slideshare.net/xzolian/… and #8172369 and a few blogs which say that the parent-child context is better than the traditional NSManagedObjectContextDidSaveNotification way. Also, according to the parent-child context I am saving the child and then the parent immediately in the nested performBlock.Still. the parent gets the nil data. I tried commenting the data fetch and only saving the data also.Nadene

© 2022 - 2024 — McMap. All rights reserved.