insertRowsAtIndexPaths/deleteRowsAtIndexPaths
/ supprime la cellule de table en utilisant insertRowsAtIndexPaths/deleteRowsAtIndexPaths
enveloppé dans beginUpdates/endUpdates
. J'utilise aussi beginUpdates/endUpdates
pour ajuster rowHeight. Toutes ces opérations sont animées par défaut.
Comment puis-je détecter la fin de l'animation lors de l'utilisation de 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 CALayer
utilisent des animations CALayer
interne. Autrement dit, ils ajoutent les animations à toute CATransaction
ouverte. S'il n'y a pas de CATransaction
ouverte (le cas normal), on commence implicitement, ce qui se termine à la fin du cycle actuel. Mais si vous en commencez un vous-même, comme c'est fait ici, alors il utilisera celui-là.
Version rapide
CATransaction.begin() CATransaction.setCompletionBlock({ do.something() }) tableView.beginUpdates() tableView.endUpdates() CATransaction.commit()
Une solution possible pourrait être d'hériter de UITableView sur lequel vous appelez endUpdates
et d'écraser setContentSizeMethod
, puisque UITableView ajuste sa taille de contenu pour correspondre aux lignes ajoutées ou supprimées. Cette approche devrait également fonctionner pour reloadData
.
Pour vous assurer qu'une notification est envoyée uniquement après l' endUpdates
de endUpdates
, vous pouvez également replace 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; } }
Vous pouvez inclure votre (vos) opération (s) dans le bloc d'animation UIView comme ceci:
- (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 .
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é quand une cellule qui est déjà dans la table se déplace de l'écran à l'écran, donc ce n'est peut-être pas exactement ce que vous cherchez. J'ai juste regardé à travers toutes les methods déléguées UITableView
et UIScrollView
et il ne semble pas y avoir quelque chose à gérer juste après qu'une cellule est une animation insérée.
Pourquoi ne pas simplement appeler la méthode que vous voulez appeler quand l'animation se termine après 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]; } }
N'a pas encore trouvé une bonne solution (à court de sous-class UITableView). J'ai décidé d'utiliser performSelector:withObject:afterDelay:
pour le moment. Pas idéal, mais fait le travail.
MISE À JOUR : Il semble que je puisse utiliser scrollViewDidEndScrollingAnimation:
à cet effet (ceci est spécifique à mon implémentation, voir le commentaire).