Does anyone know why I cannot save a change in the order of objects in an NSOrderedSet relationship in Core Data? I already know of the bug where using the generated functions for an NSOrderedSet relationship does not work well, and so I always use the keypath. Below is the code for two functions in a tableview.
The tableView:moveRowAtIndexPath:toIndexPath:
claims to save successfully, but the change is actually not saved, meaning if I perform a [tableView reloadData];
, the old order is still there. Even if I exit the app and restart it, the order has not changed. I have verfified this with multiple NSLogs. The second function, tableView:commitEditingStyle:forRowAtIndexPath:
, which I use to delete an NSOrderedSet entry, works perfectly.
My theory is that Core Data discards the order information from the NSOrderedSet relationship in its internal representation, and so because the objects remain the same, it figures it doesn't need to save anything. Has anyone experienced anything like this before? If so, did you find a work-around?
-(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); }
}
}
EDIT: I was able to solve the problem by calling [context save:&savingError]
twice, once with the records removed, and once with them reinserted in the new order. This fix shouldn't really be necessary though.
Converting @ikuramedia's code to swift gives:
var exchange: NSMutableOrderedSet = playlist.tracks.mutableCopy() as! NSMutableOrderedSet
exchange.exchangeObjectAtIndex(fromIndexPath.row, withObjectAtIndex: toIndexPath.row)
playlist.tracks = exchange
In case anyone needs it
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With