2010-03-13 11 views
8

A un certo punto della mia applicazione, ho un NSArray il cui contenuto cambia. Questi contenuti sono mostrati in UITableView. Sto cercando di trovare un modo per trovare il diff tra i contenuti di prima e dopo del NSArray così posso passare il indexPath corretto per insertRowsAtIndexPaths: withRowAnimation: and deleteRowsAtIndexPaths: withRowAnimation: per avere le animazioni ben animate. Qualche idea?Differenza di 2 NSArray per inserimento/eliminazione animati in UITableView

thx

risposta

5

Ecco è wat ho provato e sembra funzionare, se qualcuno ha qualcosa di meglio, mi piacerebbe vederlo.

[self.tableView beginUpdates]; 

NSMutableArray* rowsToDelete = [NSMutableArray array]; 
NSMutableArray* rowsToInsert = [NSMutableArray array]; 

for (NSInteger i = 0; i < oldEntries.count; i++) 
{ 
    FDEntry* entry = [oldEntries objectAtIndex:i]; 
    if (! [displayEntries containsObject:entry]) 
     [rowsToDelete addObject: [NSIndexPath indexPathForRow:i inSection:0]]; 
} 

for (NSInteger i = 0; i < displayEntries.count; i++) 
{ 
    FDEntry* entry = [displayEntries objectAtIndex:i]; 
    if (! [oldEntries containsObject:entry]) 
    [rowsToInsert addObject: [NSIndexPath indexPathForRow:i inSection:0]]; 
} 

[self.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationFade]; 
[self.tableView insertRowsAtIndexPaths:rowsToInsert withRowAnimation:UITableViewRowAnimationRight]; 

[self.tableView endUpdates]; 
+0

Ben fatto! Maledettamente difficile da ottenere questo :) –

2

Questa domanda del 2010 è ciò che ho trovato quando ero su Google. Dal momento che iOS 5.0, ora abbiamo anche -[UITableView moveRowAtIndexPath:toIndexPath] che si vuole veramente gestire. Ecco una funzione che confronta due array e genera percorsi di indicizzazione adatti per le operazioni di cancellazione, inserimento e spostamento.

- (void) calculateTableViewChangesBetweenOldArray:(NSArray *)oldObjects 
             newArray:(NSArray *)newObjects 
            sectionIndex:(NSInteger)section 
           indexPathsToDelete:(NSArray **)indexPathsToDelete 
           indexPathsToInsert:(NSArray **)indexPathsToInsert 
           indexPathsToMove:(NSArray **)indexPathsToMove 
          destinationIndexPaths:(NSArray **)destinationIndexPaths 
{ 

    NSMutableArray *pathsToDelete = [NSMutableArray new]; 
    NSMutableArray *pathsToInsert = [NSMutableArray new]; 
    NSMutableArray *pathsToMove = [NSMutableArray new]; 
    NSMutableArray *destinationPaths = [NSMutableArray new]; 

    // Deletes and moves 
    for (NSInteger oldIndex = 0; oldIndex < oldObjects.count; oldIndex++) { 
     NSObject *object = oldObjects[oldIndex]; 
     NSInteger newIndex = [newObjects indexOfObject:object]; 

     if (newIndex == NSNotFound) { 
      [pathsToDelete addObject:[NSIndexPath indexPathForRow:oldIndex inSection:section]]; 
     } else if (newIndex != oldIndex) { 
      [pathsToMove addObject:[NSIndexPath indexPathForRow:oldIndex inSection:section]]; 
      [destinationPaths addObject:[NSIndexPath indexPathForRow:newIndex inSection:section]]; 
     } 
    } 

    // Inserts 
    for (NSInteger newIndex = 0; newIndex < newObjects.count; newIndex++) { 
     NSObject *object = newObjects[newIndex]; 
     if (![oldObjects containsObject:object]) { 
      [pathsToInsert addObject:[NSIndexPath indexPathForRow:newIndex inSection:section]]; 
     } 
    } 

    if (indexPathsToDelete)  *indexPathsToDelete = [pathsToDelete copy]; 
    if (indexPathsToInsert)  *indexPathsToInsert = [pathsToInsert copy]; 
    if (indexPathsToMove)  *indexPathsToMove =  [pathsToMove copy]; 
    if (destinationIndexPaths) *destinationIndexPaths = [destinationPaths copy]; 
} 

Un esempio su come utilizzarlo. Supponiamo che tu stia visualizzando una tabella di persone, che mantieni nell'array self.people. L'indice di sezione in cui vengono visualizzate le persone è 0.

- (void) setPeople:(NSArray <Person *> *)newPeople { 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [self.tableView beginUpdates]; 

     NSArray *rowsToDelete, *rowsToInsert, *rowsToMove, *destinationRows; 

     [self calculateTableViewChangesBetweenOldArray:self.people 
               newArray:newPeople 
              sectionIndex:0 
            indexPathsToDelete:&rowsToDelete 
            indexPathsToInsert:&rowsToInsert 
             indexPathsToMove:&rowsToMove 
           destinationIndexPaths:&destinationRows 
     ]; 

     self.people = newPeople; 

     [self.tableView deleteRowsAtIndexPaths:rowsToDelete withRowAnimation:UITableViewRowAnimationFade]; 
     [self.tableView insertRowsAtIndexPaths:rowsToInsert withRowAnimation:UITableViewRowAnimationFade]; 
     [rowsToMove enumerateObjectsUsingBlock:^(NSIndexPath * _Nonnull oldIndexPath, NSUInteger idx, BOOL * _Nonnull stop) { 
      NSIndexPath *newIndexPath = destinationRows[idx]; 
      [self.tableView moveRowAtIndexPath:oldIndexPath toIndexPath:newIndexPath]; 
     }]; 

     [self.tableView endUpdates]; 
    }); 
}