首先,我想说我没有使用线程或多个上下文,而且我已经阅读并使用了我可以在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;
}
答案 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在主线程上执行引用核心数据的任何方法来解决它。