J'insère/supprime une cellule de tableau à l'aide de insertRowsAtIndexPaths/deleteRowsAtIndexPaths
enveloppé dans beginUpdates/endUpdates
J'utilise aussi beginUpdates/endUpdates
lors du réglage de rowHeight. Toutes ces opérations sont animées par défaut.
Comment puis-je détecter que l'animation s'est terminée avec beginUpdates/endUpdates
?
Et ça?
[CATransaction begin];
[CATransaction setCompletionBlock:^{
// animation has finished
}];
[tableView beginUpdates];
// do some work
[tableView endUpdates];
[CATransaction commit];
Cela fonctionne car les animations tableView utilisent des animations CALayer
en interne. C'est-à-dire qu'ils ajoutent les animations à toute CATransaction
ouverte. S'il n'y a pas de CATransaction
ouvert (le cas normal), alors l'une d'entre elles est commencée implicitement et se termine à la fin du cycle d'exécution en cours. Mais si vous en commencez un vous-même, comme c'est le cas ici, alors il l'utilisera.
Version rapide
CATransaction.begin()
CATransaction.setCompletionBlock({
do.something()
})
tableView.beginUpdates()
tableView.endUpdates()
CATransaction.commit()
Vous pouvez inclure vos opérations dans le bloc d’animation UIView de la manière suivante:
- (void)tableView:(UITableView *)tableView performOperation:(void(^)())operation completion:(void(^)(BOOL finished))completion
{
[UIView animateWithDuration:0.0 animations:^{
[tableView beginUpdates];
if (operation)
operation();
[tableView endUpdates];
} completion:^(BOOL finished) {
if (completion)
completion(finished);
}];
}
Crédits à https://stackoverflow.com/a/12905114/634940 .
Une solution possible pourrait être d'hériter de UITableView sur lequel vous appelez endUpdates
et d'écraser sa setContentSizeMethod
, puisque UITableView ajuste la taille de son contenu pour qu'elle corresponde aux lignes ajoutées ou supprimées. Cette approche devrait également fonctionner pour reloadData
.
Pour s'assurer qu'une notification est envoyée uniquement après l'appel de endUpdates
, vous pouvez également écraser endUpdates
et y définir un indicateur.
// somewhere in header
@private BOOL endUpdatesWasCalled_;
-------------------
// in implementation file
- (void)endUpdates {
[super endUpdates];
endUpdatesWasCalled_ = YES;
}
- (void)setContentSize:(CGSize)contentSize {
[super setContentSize:contentSize];
if (endUpdatesWasCalled_) {
[self notifyEndUpdatesFinished];
endUpdatesWasCalled_ = NO;
}
}
Nous n'avons pas encore trouvé de solution satisfaisante (à moins de sous-classer UITableView). J'ai décidé d'utiliser performSelector:withObject:afterDelay:
pour le moment. Pas idéal, mais fait le travail.
UPDATE: Il semble que je puisse utiliser scrollViewDidEndScrollingAnimation:
à cette fin (cela est spécifique à mon implémentation, voir le commentaire).
Vous pouvez utiliser tableView:willDisplayCell:forRowAtIndexPath:
comme:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"tableView willDisplay Cell");
cell.backgroundColor = [UIColor colorWithWhite:((indexPath.row % 2) ? 0.25 : 0) alpha:0.70];
}
Mais cela sera également appelé lorsqu'une cellule déjà présente dans la table se déplacera de l'écran à l'écran, de sorte que ce ne sera peut-être pas exactement ce que vous recherchez. Je viens de parcourir toutes les méthodes de délégué UITableView
et UIScrollView
et il ne semble pas y avoir quoi que ce soit à gérer juste après l'animation d'une cellule insérée.
Pourquoi ne pas simplement appeler la méthode que vous voulez appeler lorsque l'animation se termine après la endUpdates
?
- (void)setDownloadedImage:(NSMutableDictionary *)d {
NSIndexPath *indexPath = (NSIndexPath *)[d objectForKey:@"IndexPath"];
[indexPathDelayed addObject:indexPath];
if (!([table isDragging] || [table isDecelerating])) {
[table beginUpdates];
[table insertRowsAtIndexPaths:indexPathDelayed withRowAnimation:UITableViewRowAnimationFade];
[table endUpdates];
// --> Call Method Here <--
loadingView.hidden = YES;
[indexPathDelayed removeAllObjects];
}
}
Si vous ciblez iOS 11 ou une version ultérieure, vous devez utiliser UITableView.performBatchUpdates(_:completion:)
à la place:
tableView.performBatchUpdates({
// delete some cells
// insert some cells
}, completion: { finished in
// animation complete
})