2012-02-28 81 views
9

有谁知道为什么我无法在核心数据中以NSOrderedSet关系中的对象顺序保存更改吗?我已经知道使用NSOrderedSet关系的生成函数的效果不好,所以我总是使用keypath。下面是tableview中两个函数的代码。无法重新排列核心数据中的NSOrderedSet关系

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

我的理论是核心数据在内部表示中放弃了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]两次,一次与记录中删除来解决问题,而一旦他们在新的顺序重新插入。这个修复应该不是真的有必要。

+0

这值得庆幸的是似乎是固定的iOS 6,这意味着一个大的性能提升,如果你需要重新洗牌的大对象树木。 – sobri 2012-09-13 03:44:09

+0

您可以发布已编辑的解码代码吗?我做了你所说的,称为保存两次,但它是不够的,使其工作... – 2012-09-26 21:35:46

+0

这已修复在iOS6?有趣的是它仍然不适合我哈哈! :')在我的经验中,核心数据在已经存在的情况下编辑是一件痛苦的事情!寻找解决这个类似的问题! – simonthumper 2013-06-22 20:38:33

回答

8

转换为数组的原因是什么? 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];一切其他方法应该是多余的(除了保存上下文)。

2

转换@ ikuramedia的代码来迅速得到:

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

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

playlist.tracks = exchange 

万一有人需要它