2010-03-13 5 views
8

À un certain moment dans mon application, j'ai un NSArray dont le contenu change. Ces contenus sont affichés dans un UITableView. J'essaie de trouver un moyen de trouver la différence entre le contenu d'avant et après de NSArray afin que je puisse passer les indexPaths correct à insertRowsAtIndexPaths: withRowAnimation: et deleteRowsAtIndexPaths: withRowAnimation: afin que les changements soient bien animés. Des idées?Différence de 2 NSArray pour l'insertion/suppression animée dans UITableView

thx

Répondre

5

Voici est wat je l'ai essayé et il semble fonctionner, si quelqu'un a quelque chose de mieux, j'aimerais le voir.

[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

Bravo! Sanglant difficile à obtenir :) –

2

Cette question de 2010 est ce que j'ai trouvé quand j'étais googling. Depuis iOS 5.0, nous avons maintenant aussi -[UITableView moveRowAtIndexPath:toIndexPath] que vous voulez vraiment gérer. Voici une fonction qui compare deux tableaux et génère des chemins d'index appropriés pour les opérations de suppression, d'insertion et de déplacement.

- (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 exemple sur la façon de l'utiliser. Supposons que vous affichez une table de personnes, que vous conservez dans le tableau self.people. L'index de la section où les personnes sont affichées est 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]; 
    }); 
}