Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Core Data error 133020: problems merging in a save:

First off I want to say that I am not using threads or multiple contexts and I have read and worked from every related answer I could find on SO. I have a project which I have added Core Data to and am finding it impossible to find a pernicious bug. I can reproduce the bug every time using the following code.

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath   {

    OT_Track *track;

    track = [[self.tracksArray objectAtIndex: fromIndexPath.row] retain];
    [self.tracksArray removeObjectAtIndex: fromIndexPath.row];
    [self.tracksArray insertObject:track atIndex: toIndexPath.row];
    [track release];

    for( int n = 0; n < [self.tracksArray count]; n++ ) {
        track = [self.tracksArray objectAtIndex:n];
        track.positionInPlaylist = [NSNumber numberWithInteger:n];
    }

    if( [self.managedObjectContext hasChanges] && ![self.managedObjectContext save:&error] )    {
        NSLog(@"Unable to Save Core Data Context");
    }
}

self.tracksArray is an NSMutableArray populated from a fetch performed in viewWillAppear. OT_Track is an Entity defined in my momd which has a field called positionInPlaylist (defined as Integer32). positionInPlaylist stores the position of an OT_Track in an OT_Playlist which allows the user to re-order items in the playlist.

I would be so grateful for any assistance on this as it's driving me nuts!

the error I am getting is..

**************  Error  ********    The operation couldn’t be completed. (Cocoa error 133020.)
2012-03-27 13:03:32.578 OneTrack[7693:707]   detailedErrors: (null)
2012-03-27 13:03:32.587 OneTrack[7693:707]   {
    conflictList =     (
        "NSMergeConflict (0x4018590) for NSManagedObject (0x40d7e60) with objectID '0x40debd0 <x-coredata://3A300D46-4B20-46DA-A82E-0785BFFAFF14/OT_Track/p2642>' with oldVersion = 1 and newVersion = 2 and old cached row = {\n    artistName = \"Ladysmith Black Mambazo\";\n    disabled = 0;\n    persistentID = \"-2511068126837362989\";\n    playing = 0;\n    playlist = \"0x401a7a0 <x-coredata://3A300D46-4B20-46DA-A82E-0785BFFAFF14/OT_Playlist/p62>\";\n    podcast = 0;\n    positionInPlaylist = 0;\n    trackAutoplay = 0;\n    trackEndTime = \"222.563\";\n    trackLoop = 0;\n    trackMaxTime = \"222.563\";\n    trackName = Abezizwe;\n    trackPredelay = 0;\n    trackSignature = 2;\n    trackStartTime = 0;\n    trackTempo = 120;\n    trackVolume = 1;\n} and new database row = {\n    artistName = \"Ladysmith Black Mambazo\";\n    disabled = 0;\n    persistentID = \"-2511068126837362989\";\n    playing = 0;\n    playlist = \"0x40188b0 <x-coredata://3A300D46-4B20-46DA-A82E-0785BFFAFF14/OT_Playlist/p62>\";\n    podcast = 0;\n    positionInPlaylist = 2;\n    trackAutoplay = 0;\n    trackEndTime = \"222.563\";\n    trackLoop = 0;\n    trackMaxTime = \"222.563\";\n    trackName = Abezizwe;\n    trackPredelay = 0;\n    trackSignature = 2;\n    trackStartTime = 0;\n    trackTempo = 120;\n    trackVolume = 1;\n}",
        "NSMergeConflict (0x4018610) for NSManagedObject (0x40dc990) with objectID '0x40deed0 <x-coredata://3A300D46-4B20-46DA-A82E-0785BFFAFF14/OT_Track/p2645>' with oldVersion = 1 and newVersion = 2 and old cached row = {\n    artistName = \"Warren Zevon\";\n    disabled = 0;\n    persistentID = \"-2511068126837362101\";\n    playing = 0;\n    playlist = \"0x401ac40 <x-coredata://3A300D46-4B20-46DA-A82E-0785BFFAFF14/OT_Playlist/p62>\";\n    podcast = 0;\n    positionInPlaylist = 3;\n    trackAutoplay = 0;\n    trackEndTime = \"223.686\";\n    trackLoop = 0;\n    trackMaxTime = \"223.686\";\n    trackName = \"Accidentally Like A Martyr\";\n    trackPredelay = 0;\n    trackSignature = 2;\n    trackStartTime = 0;\n    trackTempo = 120;\n    trackVolume = 1;\n} and new database row = {\n    artistName = \"Warren Zevon\";\n    disabled = 0;\n    persistentID = \"-2511068126837362101\";\n    playing = 0;\n    playlist = \"0x4018420 <x-coredata://3A300D46-4B20-46DA-A82E-0785BFFAFF14/OT_Playlist/p62>\";\n    podcast = 0;\n    positionInPlaylist = 3;\n    trackAutoplay = 0;\n    trackEndTime = \"223.686\";\n    trackLoop = 0;\n    trackMaxTime = \"223.686\";\n    trackName = \"Accidentally Like A Martyr\";\n    trackPredelay = 0;\n    trackSignature = 2;\n    trackStartTime = 0;\n    trackTempo = 120;\n    trackVolume = 1;\n}"
    );
}

self.tracksArray is populated by the following method called from viewWillAppear…

- (BOOL) populateTracksArray    {

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"OT_Track" inManagedObjectContext:self.managedObjectContext];
    [request setEntity:entity];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"positionInPlaylist" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [request setSortDescriptors:sortDescriptors];
    NSPredicate *fetchPredicate = [NSPredicate predicateWithFormat:@"playlist == %@", currentUserPlaylist];
    [request setPredicate:fetchPredicate];
    [sortDescriptors release];
    [sortDescriptor release];

    NSError *error = nil;
    NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
    if (mutableFetchResults == nil) { // Handle the error.
        return false;
    }

    [self setTracksArray:mutableFetchResults];
    [mutableFetchResults release];
    [request release];

    return true;
}
like image 285
amergin Avatar asked Mar 27 '12 13:03

amergin


People also ask

Could not merge changes Core Data?

Problem: You see the error message, " Could not merge changes ." Cause: Two different managed object contexts tried to change the same data. This is also known as an optimistic locking failure. Remedy: Either set a merge policy on the context, or manually (programmatically) resolve the failure.

How do I get NSManagedObject?

Still inside the Core Data editor, go to the Editor menu and choose Create NSManagedObject Subclass. Make sure your data model is selected then click Next. Make sure the Commit entity is checked then click Next again.


2 Answers

Have you tried setting the merge policy on your managed object context?

The default is NSErrorMergePolicy which will just throw errors. Your other options are here.

I'd suggest this one :

[self.managedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

Just noticed something that might be causing problems in your swapping tracks code.

Instead of

OT_Track *track;

track = [[self.tracksArray objectAtIndex: fromIndexPath.row] retain];
[self.tracksArray removeObjectAtIndex: fromIndexPath.row];
[self.tracksArray insertObject:track atIndex: toIndexPath.row];
[track release];

try the code snippet from this blog post.

I think that your track swapping code might be getting indexes confused halfway through the swap.

like image 123
deanWombourne Avatar answered Nov 03 '22 01:11

deanWombourne


I'm still not really sure what caused this but the issue reoccurred and I solved it by ensuring that any methods that referenced core data were executed on the main thread using performSelectorOnMainThread.

like image 20
amergin Avatar answered Nov 03 '22 00:11

amergin