Mise à jouruitableview: suppression de sections avec animation
J'ai posté ma solution à ce problème comme une réponse ci-dessous. Cela prend une approche différente de ma première révision.
Original Question J'ai déjà posé une question sur le SO que je pensais résolu mes problèmes:
How to deal with non-visible rows during row deletion. (UITableViews)
Cependant, j'ai maintenant des problèmes similaires à nouveau lors de la suppression des sections d'un UITableView. (ils ont refait surface lorsque j'ai modifié le nombre de sections/lignes dans le tableau). Avant que je ne vous perde à cause de la longueur de mon message, permettez-moi d'énoncer le problème clairement, et vous pouvez lire autant que nécessaire pour fournir une réponse.
Problème:
Si lots suppression de lignes et les sections d'un UITableView, l'application se bloque parfois. Cela dépend de la configuration de la table et de la combinaison de lignes et de sections que je choisis de supprimer.
Le journal dit, je suis tombé parce qu'il dit que je ne l'ai pas mis à jour la source de données et la table correctement:
Invalid update: invalid number of rows in section 5. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted).
maintenant rapidement, avant d'écrire la réponse évidente, je vous assure que je l'ai fait ajouter et supprimer la lignes et sections correctement à partir de la source de données. L'explication est longue, mais vous la trouverez ci-dessous, en suivant la méthode.
Donc, avec cela, si vous êtes toujours intéressé ...
méthode qui gère l'enlèvement des sections et des lignes:
- (void)createFilteredTableGroups{
//index set to hold sections to remove for deletion animation
NSMutableIndexSet *sectionsToDelete = [NSMutableIndexSet indexSet];
[sectionsToDelete removeIndex:0];
//array to track cells for deletion animation
NSMutableArray *cellsToDelete = [NSMutableArray array];
//array to track controllers to delete from presentation model
NSMutableArray *controllersToDelete = [NSMutableArray array];
//for each section
for(NSUInteger i=0; i<[tableGroups count];i++){
NSMutableArray *section = [tableGroups objectAtIndex:i];
//controllers to remove
NSMutableIndexSet *controllersToDeleteInCurrentSection = [NSMutableIndexSet indexSet];
[controllersToDeleteInCurrentSection removeIndex:0];
NSUInteger indexOfController = 0;
//for each cell controller
for(ScheduleCellController *cellController in section){
//bool indicating whether the cell controller's cell should be removed
NSString *shouldDisplayString = (NSString*)[[cellController model] objectForKey:@"filteredDataSet"];
BOOL shouldDisplay = [shouldDisplayString boolValue];
//if it should be removed
if(!shouldDisplay){
NSIndexPath *cellPath = [self indexPathOfCellWithCellController:cellController];
//if cell is on screen, mark for animated deletion
if(cellPath!=nil)
[cellsToDelete addObject:cellPath];
//marking controller for deleting from presentation model
[controllersToDeleteInCurrentSection addIndex:indexOfController];
}
indexOfController++;
}
//if removing all items in section, add section to removed in animation
if([controllersToDeleteInCurrentSection count]==[section count])
[sectionsToDelete addIndex:i];
[controllersToDelete addObject:controllersToDeleteInCurrentSection];
}
//copy the unfiltered data so we can remove the data that we want to filter out
NSMutableArray *newHeaders = [tableHeaders mutableCopy];
NSMutableArray *newTableGroups = [[allTableGroups mutableCopy] autorelease];
//removing controllers
int i = 0;
for(NSMutableArray *section in newTableGroups){
NSIndexSet *indexesToDelete = [controllersToDelete objectAtIndex:i];
[section removeObjectsAtIndexes:indexesToDelete];
i++;
}
//removing empty sections and cooresponding headers
[newHeaders removeObjectsAtIndexes:sectionsToDelete];
[newTableGroups removeObjectsAtIndexes:sectionsToDelete];
//update headers
[tableHeaders release];
tableHeaders = newHeaders;
//storing filtered table groups
self.filteredTableGroups = newTableGroups;
//filtering animation and presentation model update
[self.tableView beginUpdates];
tableGroups = self.filteredTableGroups;
[self.tableView deleteSections:sectionsToDelete withRowAnimation:UITableViewRowAnimationTop];
[self.tableView deleteRowsAtIndexPaths:cellsToDelete withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
//marking table as filtered
self.tableIsFiltered = YES;
}
Je pense:
Le probl em semble être ceci: Si vous regardez ci-dessus où je liste le nombre de cellules dans chaque section, vous verrez que la section 5 semble augmenter de 1. Cependant, ce n'est pas vrai. La section 5 originale a été supprimée et une autre section a pris sa place (en particulier, il s'agit de l'ancienne section 10). Pourquoi la vue de la table semble-t-elle ne pas s'en rendre compte? Pourquoi? Il devrait savoir que j'ai supprimé l'ancienne section et ne devrait pas s'attendre à ce qu'une nouvelle section qui se trouve maintenant à l'index de l'ancienne section soit liée par le nombre de lignes de la section supprimée.
J'espère que cela a du sens, c'est un peu compliqué de l'écrire.
(Notez que ce code a déjà fonctionné avec un nombre différent de lignes/sections.cette configuration particulière semble donner des problèmes)
Vous pouvez également suivre l'indexPath pour chaque cellule dont vous devez vous débarrasser et les ajuster de manière appropriée au cours de vos suppressions. (Cela peut être la manière longue/alambiquée/inappropriée de le faire - juste une pensée.) – Tim
Je fais une suppression par lot, donc cela ne fait aucune différence dans l'ordre dans lequel je liste les opérations. La vue de table effectue des opérations "à la fois" lorsqu'elles se trouvent dans le bloc de mise à jour. Comme j'étais paranoïaque, j'ai essayé de changer l'ordre des opérations en vain. La numérotation des sections/lignes ne change pas (ne devrait pas changer) pendant la suppression du lot. Si n'utilisait pas les blocs, vous auriez raison. –
@Tim Pensée intéressante. Vous avez raison, cela pourrait être assez fastidieux avec une grande quantité de suppressions (que je vais avoir). Je me demande aussi si je pourrais faire des suppressions multiples en succession rapide. J'essayais de faire des suppressions de lots afin d'éviter ces problèmes, mais cela peut être nécessaire. –