Core Data error 133020: problems merging in a save:
Asked Answered
J

2

11

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;
}
Jett answered 27/3, 2012 at 13:57 Comment(0)
J
8

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.

Jett answered 5/4, 2012 at 15:53 Comment(0)
R
19

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.

Ravishing answered 27/3, 2012 at 14:12 Comment(5)
Thanks for your suggestion Dean. I tried the above with NSMergeByPropertyObjectTrumpMergePolicy and things froze at the save: so I tried with NSOverwriteMergePolicy and things froze again. I'm not sure how to analyze what's going on when it freezes as the console output just stops. I will add that I can save the context after other edits (e.g. delete a track or playlist).Jett
I've spotted something that might be causing problems in your swapping tracks code - I've added a link to a blog post that has a solution that might help.Ravishing
Created the category as suggested in the blog post but it had no effect, I'm still stuck with either the merge error or a freeze if I implement the mergePolicy. I am most grateful for your help in this.Jett
I tried with a mergePolicy of NSRollbackMergePolicy and it works but obviously doesn't update the context. I also tried setting another of the fields, track.trackAutoplay, which is a BOOL just in case there was some issue with an integer32 but that had same issue.Jett
This is bizarre but it looks like if I put the save: inside the loop then the merge error disappears! Do you have any idea why this would be?Jett
J
8

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.

Jett answered 5/4, 2012 at 15:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.