2012-02-28 39 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 

萬一有人需要它