核心数据错误133020:在保存中合并的问题:

时间:2012-03-27 13:57:15

标签: iphone ios core-data

首先,我想说我没有使用线程或多个上下文,而且我已经阅读并使用了我可以在SO上找到的每个相关答案。我有一个项目,我已经添加了核心数据,并发现无法找到一个有害的bug。我每次都可以使用以下代码重现该错误。

- (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是一个NSMutableArray,由在viewWillAppear中执行的提取填充。 OT_Track是我妈妈中定义的一个实体,它有一个名为positionInPlaylist的字段(定义为Integer32)。 positionInPlaylist将OT_Track的位置存储在OT_Playlist中,允许用户重新排序播放列表中的项目。

如果有任何帮助,我会非常感激,因为它让我疯了!

我得到的错误是..

**************  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由来自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;
}

2 个答案:

答案 0 :(得分:17)

您是否尝试在托管对象上下文中设置合并策略?

默认值为NSErrorMergePolicy,只会抛出错误。你的other options are here

我建议这个:

[self.managedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];

刚刚发现可能导致交换曲目代码问题的内容。

而不是

OT_Track *track;

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

尝试this blog post中的代码段。

我认为你的轨道交换代码可能会让交换中途的索引混乱。

答案 1 :(得分:8)

我仍然不确定导致这个问题的原因,但问题再次发生,我通过确保使用performSelectorOnMainThread在主线程上执行引用核心数据的任何方法来解决它。