2012-02-28 9 views
9

¿Alguien sabe por qué no puedo guardar un cambio en el orden de los objetos en una relación NSOrderedSet en Core Data? Ya conozco el error por el que el uso de las funciones generadas para una relación NSOrderedSet no funciona bien, por lo que siempre utilizo Keypath. A continuación se muestra el código para dos funciones en una vista de tabla.No se puede reordenar una relación NSOrderedSet en Core Data

El tableView:moveRowAtIndexPath:toIndexPath: dice que se guardó correctamente, pero el cambio en realidad no se guarda, lo que significa que si realizo un [tableView reloadData];, el pedido anterior sigue ahí. Incluso si salgo de la aplicación y la reinicio, el pedido no ha cambiado. Lo he verificado con múltiples NSLogs. La segunda función, tableView:commitEditingStyle:forRowAtIndexPath:, que utilizo para eliminar una entrada NSOrderedSet, funciona perfectamente.

Mi teoría es que Core Data descarta la información de la orden de la relación NSOrderedSet en su representación interna, y como los objetos permanecen iguales, cree que no necesita guardar nada. Alguien ha experimentado algo como esto antes? Si es así, ¿encontró una solución alternativa?

-(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: que fue capaz de resolver el problema llamando a [context save:&savingError] dos veces, una vez con los registros eliminados, y una vez con ellos se vuelven a insertar en el nuevo orden. Sin embargo, esta corrección no debería ser realmente necesaria.

+0

Esta suerte parece estar fijo en iOS 6. Lo que significa una gran mejora en el rendimiento si es necesario barajar objeto grande árboles. – sobri

+0

¿Puedes publicar el código resuelto editado, por favor? Hice lo que dijiste, llamando a ahorrar dos veces, pero no fue suficiente para hacerlo funcionar ... –

+0

¿Esto se solucionó en iOS6? Es gracioso, todavía no funciona para mí jaja! : ') ¡Core Data es un dolor en el culo para editar cosas una vez que ya está ahí en mi experiencia! ¡Buscando resolver un problema similar a esto! – simonthumper

Respuesta

8

¿Cuál es el motivo de la conversión a una matriz? NSMutableOrderedSet ya es compatible con el método exchangeObjectAtIndex:withObjectAtIndex:

me gustaría sugerir:

NSMutableOrderedSet *exchange = [playlist.tracks mutableCopy]; 

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

[exchange exchangeObjectAtIndex:fromIndex withObjectAtIndex:toIndex]; 

playlist.tracks = exchange; 

Además, parecen tener una relación muchos a muchos entre la reproducción y la pista, por lo que su método de eliminación funciona debido a su llamada a [track removeBelongingPlaylistObject:playlist]; Todo else en el método debería ser redundante (excepto para guardar el contexto).

2

la conversión @ código de ikuramedia al veloz da:

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

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

playlist.tracks = exchange 

En caso de que alguien lo necesita