2012-02-28 19 views
9

Czy ktoś wie, dlaczego nie mogę zapisać zmiany w kolejności obiektów w relacji NSOrderedSet w danych podstawowych? Już wiem o błędzie, w którym używanie wygenerowanych funkcji dla relacji NSOrderedSet nie działa dobrze, więc zawsze używam klawisza keypath. Poniżej znajduje się kod dla dwóch funkcji w widoku tabeli.Nie można zmienić kolejności relacji NSOrderedSet w danych podstawowych

Zgłoszenie służy do zapisania, ale zmiana nie jest zapisana, co oznacza, że ​​jeśli wykonuję [tableView reloadData];, stara kolejność nadal istnieje. Nawet jeśli wyjdę z aplikacji i zrestartuję ją, kolejność się nie zmieni. Weryfikowaliśmy to za pomocą wielu NSLogów. Druga funkcja, tableView:commitEditingStyle:forRowAtIndexPath:, której używam do usunięcia wpisu NSOrderedSet, działa idealnie.

Moja teoria mówi, że Core Data odrzuca informacje o zamówieniu ze związku NSOrderedSet w jego wewnętrznej reprezentacji, a ponieważ obiekty pozostają takie same, to nie musi niczego zapisywać. Czy ktoś wcześniej doświadczył czegoś podobnego? Jeśli tak, czy znalazłeś jakieś obejście?

-(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: udało mi się rozwiązać ten problem poprzez wywołanie [context save:&savingError] dwukrotnie, raz usunięte rekordy, a raz z nimi ponownie włączyć do nowego porządku. Ta poprawka nie powinna jednak być konieczna.

+0

To na szczęście wydaje się być ustalona w iOS 6. Co oznacza duży wzrost wydajności, jeśli trzeba przetasować dużego obiektu drzewa. – sobri

+0

Czy możesz opublikować edytowany, rozwiązany kod? Zrobiłem to, co powiedziałeś, dzwoniąc dwa razy, ale to nie wystarczyło, żeby zadziałało ... –

+0

Naprawiono to w iOS6? Zabawne, wciąż nie działa dla mnie haha! : ') Core Data to ból w tyłku do edycji rzeczy, które już są w moim doświadczeniu! Szuka rozwiązania podobnego problemu do tego! – simonthumper

Odpowiedz

8

Jaki jest powód konwersji do tablicy? NSMutableOrderedSet już obsługuje metodę exchangeObjectAtIndex:withObjectAtIndex:

sugeruję:

NSMutableOrderedSet *exchange = [playlist.tracks mutableCopy]; 

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

[exchange exchangeObjectAtIndex:fromIndex withObjectAtIndex:toIndex]; 

playlist.tracks = exchange; 

Ponadto, wydaje się mieć wiele do wielu relacji między playlisty i trasę, a więc usuwania metoda działa z powodu rozmowy do [track removeBelongingPlaylistObject:playlist]; Wszystko w przeciwnym razie metoda powinna być redundantna (z wyjątkiem zapisania kontekstu).

2

Konwersja @ kodu ikuramedia do szybkich daje:

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

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

playlist.tracks = exchange 

na wypadek gdyby ktoś go potrzebuje

Powiązane problemy