Why am I getting a merge error while keeping NSManagedObjectContext in this "clean"?

Thanks in advance for any help. I fought this today and I think there is something seriously wrong with my understanding of how the structure works.

I am working on a main data application where entities have parent / child relationships. At startup, the application creates an NSManagedObjectContext (MOC). When the application is launched for the first time, it uses an asynchronous block to import the contents of the plist into the second MOC (the root of the node is obtained from the main MOC using the URI and -managedObjectIDForURIRepresentation :), immediately before the block, it stores the second context.

In my data controller, I subscribe to NSManagedObjectContextDidSaveNotification, and the following code runs when a notification is sent:

- (void)backgroundContextDidSave:(NSNotification *)notification {
    if(![notification.object isEqual:self.managedObjectContext]){
        if (![NSThread isMainThread]) {
            [self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
                                   withObject:notification
                                waitUntilDone:NO];
            return;
    }       
        [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];        ;
    }
}

I did a test of the health of this code and, of course, when the second MOC saves, it is called from the thread executing the block, then it is deferred and launched from the main thread. The notification object contains all the objects imported into the second MOC, including two that we will deal with in the following.

When this is over, I run the following code, which is in a subclass of NSManagedObject, to which the objects belong, it is just designed to remove a child from its parent:

TreeEntry *oldParent=self.parent; //keep a pointer to the old parent around so we can delete self from the children

// These next four lines are a sanity check to make sure that both objects are on the same MOC we're saving
NSManagedObjectContext *selfContext=self.managedObjectContext;
NSManagedObjectContext *parentContext=self.parent.managedObjectContext;
NSManagedObjectContext *sharedContext=[[DataController sharedDataController] managedObjectContext];
assert([selfContext isEqual:parentContext] && [selfContext isEqual:sharedContext]);

// now we fault the two objects to make sure we can not possibly have them or any changes 
// to them in the state of the main MOC, by this time the second MOC is long gone
[sharedContext refreshObject:self.parent mergeChanges:NO];
[sharedContext refreshObject:self mergeChanges:NO]; 

// up to this point, sharedContex.insertedObjects, sharedContext.updatedObects and sharedContext.deletedObjects
// have all contained no objects at all. None of the above was necessary as the MOC held no changes at all
[sharedContext saveChanges]; // we save it to, well, just to make sure I guess, I may be going crazy

// Now we carry out two changes to the objects, problem occurs if only one change is carried out,
// I'm showing both to show that there relationship is being kept consistent and valid
self.parent=nil;
[oldParent removeChild:self];


// When the next line is run the save fails with a merge conflict
[sharedContext saveChanges];

The last crash persists with error 133020 Cocoa, which is a merge merge. Two NSMergeConflicts errors in error refer to the records we are dealing with (self and self.parent).

, . , . , , , . ? , .

, , , , .

? , , , , !

+3
1

, , , , , NSManagedStoreCoordinator.

, , , -, NSManagedStoreCoordinator ( ) .

MOC, , , , . . [MOC setStalenessInterval: 0.0] .

+7

Source: https://habr.com/ru/post/1788202/


All Articles