无法在Core Data中重新排序NSOrderedSet关系

时间:2012-02-28 16:28:02

标签: iphone objective-c uitableview core-data

有谁知道为什么我无法在Core Data中的NSOrderedSet关系中保存对象顺序的变化?我已经知道将生成的函数用于NSOrderedSet关系的错误并不好用,所以我总是使用keypath。下面是tableview中两个函数的代码。

tableView:moveRowAtIndexPath:toIndexPath:声称保存成功,但实际上未保存更改,这意味着如果我执行[tableView reloadData];,旧订单仍然存在。即使我退出应用程序并重新启动它,订单也没有改变。我用多个NSLog验证了这一点。我用来删除NSOrderedSet条目的第二个函数tableView:commitEditingStyle:forRowAtIndexPath:非常有效。

我的理论是核心数据在其内部表示中丢弃来自NSOrderedSet关系的订单信息,因此因为对象保持不变,所以它认为它不需要保存任何东西。以前有没有经历过这样的事情?如果是这样,你找到了解决办法吗?

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

    NSManagedObjectContext *context= [self managedObjectContext];

    Playlist *playlist = (Playlist*) [context objectWithID:playlistID];


    [playlist willChangeValueForKey:@"tracks"];
    NSMutableOrderedSet *exchange = [playlist mutableOrderedSetValueForKey:@"tracks"];;

    NSInteger fromIndex = sourceIndexPath.row;
    NSInteger toIndex = destinationIndexPath.row;

    NSMutableArray *arrayOfTracks = [NSMutableArray arrayWithArray:[exchange array]];

    [arrayOfTracks exchangeObjectAtIndex:fromIndex withObjectAtIndex:toIndex];
    [[playlist mutableOrderedSetValueForKey:@"tracks"] removeAllObjects];


    [[playlist mutableOrderedSetValueForKey:@"tracks"] addObjectsFromArray:arrayOfTracks];
    playlist.md5Hash = nil;
    [playlist didChangeValueForKey:@"tracks"];

    NSError *savingError = nil;
    if ([context save:&savingError]){
        NSLog(@"Successfully saved the context for reorder"); 
    } else {
        NSLog(@"Failed to save the context. Error = %@", savingError); }

}


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        NSManagedObjectContext *context= [self managedObjectContext];

        Playlist *playlist = (Playlist*) [context objectWithID:playlistID];

        Track *track = [self.tracksFRC objectAtIndexPath:indexPath];    


        NSMutableOrderedSet *exchange = [NSMutableOrderedSet orderedSetWithOrderedSet: playlist.tracks];


        [exchange removeObject:track];
        [track removeBelongingPlaylistObject:playlist];
        NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [playlist.tracks count])];

        [[playlist mutableOrderedSetValueForKey:@"tracks"] replaceObjectsAtIndexes:indexSet withObjects:[exchange array]];

        playlist.md5Hash = nil;

        NSError *savingError = nil;
        if ([context save:&savingError]){
            NSLog(@"Successfully saved the context for remove entry"); 
        } else {
            NSLog(@"Failed to save the context. Error = %@", savingError); }
    }
}

编辑:我能够通过调用[context save:&savingError]两次来解决问题,一次删除记录,一次重新插入新订单。但是,这个修复不应该是必要的。

2 个答案:

答案 0 :(得分:9)

转换为数组的原因是什么? NSMutableOrderedSet已经支持方法exchangeObjectAtIndex:withObjectAtIndex:

我建议:

NSMutableOrderedSet *exchange = [playlist.tracks mutableCopy];

NSInteger fromIndex = sourceIndexPath.row;
NSInteger toIndex = destinationIndexPath.row;

[exchange exchangeObjectAtIndex:fromIndex withObjectAtIndex:toIndex];

playlist.tracks = exchange;

此外,您似乎在播放列表和曲目之间存在多对多关系,因此您的删除方法可以正常工作,因为您调用[track removeBelongingPlaylistObject:playlist];方法中的其他所有内容都应该是多余的(保存上下文除外)。

答案 1 :(得分:2)

将@ ikuramedia的代码转换为swift给出:

var exchange: NSMutableOrderedSet = playlist.tracks.mutableCopy() as! NSMutableOrderedSet

exchange.exchangeObjectAtIndex(fromIndexPath.row, withObjectAtIndex: toIndexPath.row)

playlist.tracks = exchange

如果有人需要它