Master data concurrency with NSPersistentContainer

NOTE . I looked through similar assignments but couldn't find one that describes this situation.

I am considering the following code example from Apple regarding Core Data concurrency ( https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/Concurrency.html )

NSArray *jsonArray = …;
NSPersistentContainer *container = self.persistentContainer;
[container performBackgroundTask:^(NSManagedObjectContext *context) {
    for (NSDictionary *jsonObject in jsonArray) {
        AAAEmployeeMO *mo = [[AAAEmployeeMO alloc] initWithContext:context];
        [mo populateFromJSON:jsonObject];
    }
    NSError *error = nil;
    if (![context save:&error]) {
        NSLog(@"Failure to save context: %@\n%@", [error localizedDescription], [error userInfo]);
        abort();
    }
}];

      

In my application, the save doesn't start until the user closes the save button on the screen. How do I go about doing this, should I instead use a child context for this situation where the private context is a VC property?

NSArray *jsonArray = …; //JSON data to be imported into Core Data
NSManagedObjectContext *moc = self.persistentContainer.viewContext; //Our primary context on the main queue

NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[private setParentContext:moc];

[private performBlock:^{
    for (NSDictionary *jsonObject in jsonArray) {
        NSManagedObject *mo = …; // WHICH CONTEXT TO USE?  <<<======
        //update MO with data from the dictionary
    }
    NSError *error = nil;
    if (![private save:&error]) {
        NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
        abort();
    }
}

      

And then as soon as the user clicks do the following:

NSManagedObjectContext *moc = self.persistentContainer.viewContext; //Our primary context on the main queue
   [moc performBlockAndWait:^{
            NSError *error = nil;
            if (![moc save:&error]) {
                NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]);
                abort();
            }
        }];
    }];

      

Also note the question which moc to use in the above example (<<=====)

EDIT: . In the end I ended up creating a child context so that the table only uses viewContext

to display the results. If the user logs out without saving, I will delete all results from again viewContext

. The save button still exists, but now only a flag is set to indicate not deleting the results.

0


source to share


1 answer


If you have one page of forms and want to save it when the user clicks the save button, just grab the data from the text fields (or whatever your data) and put it in the master data using performBackgroundTask

, Since the data is only stored in the text fields, while the user is editing, if the user discards their changes will be lost.

If you have a lot of changes in a complex document with a lot of different objects that the user can create or destroy or link, and all this is only saved when the user clicks on save, then you should use a child context. You will display the data based on values ​​in the child context, but only push those changes into the parent context if the user clicks on save. This is a very rare situation, and I have never encountered the need for it.



I strongly suspect that you are in the first case. Don't use childish context. Use performBackgroundTask

and save data when the user clicks the Save button.

(also the correct context to use inside a block [private performBlock:^{

is context private

)

+1


source







All Articles