Search code examples
ioscore-dataconcurrencynsmanagedobjectnsmanagedobjectcontext

How to "tell" a parent context which managed objects it has to delete and/or insert?


I have a parent NSmanagedObjectContext in the main queue, and a child NSManagedObjectContext in a private queue. I pass a set of managed objects in the parent context to its child. Then, the child context have the managed objects from its parent, and then it is inserted new managed objects. I make some processing in the private queue with all the managed objects in the child context, the ones that came from the parent and its own new ones, and at the end of the process, I need to tell the parent:

  • Which of its managed objects need to be deleted
  • Which of its managed objects need to be replaced with the new managed objects in the child
  • Which of the managed objects in the child need to be inserted into the parent

Is it possible to do that with a parent/child relationship between contexts? Even if they belong to different queues? Or is a parent/child relationship only suitable to perform changes in the attributes of certain managed objects, but it is not for deletions and insertions of managed objects?

If it is not possible to manage this scenario with a parent/child relationship, what the approach should be?

Thanks in advance

EDIT: The examples I find just use a child context to edit a managed object of the parent and then apply the changes to the parent when edition ends. So I'm not sure if it is possible to use a child context to also delete or insert objects in the parent.


Solution

  • Here is a code snippet (with some chunks missing) that does a child based delete and then passes it up to the parent.

    [childContext performBlock:^{
        // query array of messages
    
        // LOTS OF CODE
    
        // Loop through them and delete each message
    
    
        // Loop through each message
        for (id emptyMessage in emptyMessages) {
    
            i++;
            // Work in ContextBlocks...
            //            [childContext performBlock:^{
    
            __block AHRSMessage *msg = (AHRSMessage *) [childContext objectWithID:emptyMessage];
    
            [childContext deleteObject:msg];
    
    
            if (i % modFactor == 0) {
                self.percentDone = i / totalRecords;
    
                NSLog(@"%.1f Saving ...", self.percentDone * 100);
    
    
                NSError *error;
                if (![childContext save:&error]) {
                    NSLog(@"\n error => %@ \n", [error localizedDescription]);
                    NSLog(@" error => %@ ", [error userInfo]);
                    [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]];
    
                    //                    abort();
                }
    
                [parentContext performBlock:^{
                    NSError *errrror;
                    if (![parentContext save:&errrror]) {
                        NSLog(@"\n error => %@ \n", [error localizedDescription]);
                        NSLog(@" error => %@ ", [error userInfo]);
                        [NSException raise:@"Database Write Error" format:@"%@ %@", [error localizedDescription], [error userInfo]];
    
                        //                        abort();
                    }
                }];
            }
    
            //            }];
    
        }
    

    The child save writes it to memory and to actually write to disk you have to call the parent save. As you see i do one after another - but this is not required.