iphone - started - Cómo detectar que la animación ha finalizado en UITableView beginUpdates/endUpdates?
ios getting started (6)
¿Qué hay de esto?
[CATransaction begin];
[CATransaction setCompletionBlock:^{
// animation has finished
}];
[tableView beginUpdates];
// do some work
[tableView endUpdates];
[CATransaction commit];
Esto funciona porque las animaciones CALayer
usan animaciones CALayer
internamente. Es decir, agregan las animaciones a cualquier CATransaction
abierta. Si no existe una CATransaction
abierta (el caso normal), entonces una comienza implícitamente, que finaliza al final del recorrido actual. Pero si comienzas uno tú mismo, como se hace aquí, entonces usará ese.
Estoy insertando / eliminando celda de tabla usando insertRowsAtIndexPaths/deleteRowsAtIndexPaths
envuelto en beginUpdates/endUpdates
. También estoy usando beginUpdates/endUpdates
al ajustar rowHeight. Todas estas operaciones están animadas por defecto.
¿Cómo puedo detectar que la animación ha finalizado al usar beginUpdates/endUpdates
?
Aún no he encontrado una buena solución (a falta de subclasificar UITableView). Decidí usar performSelector:withObject:afterDelay:
por ahora. No es ideal, pero hace el trabajo.
ACTUALIZACIÓN : parece que puedo usar scrollViewDidEndScrollingAnimation:
para este propósito (esto es específico para mi implementación, ver comentario).
Puede encerrar su (s) operación (es) en el bloque de animación UIView así:
- (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éditos a https://.com/a/12905114/634940 .
Puede usar tableView:willDisplayCell:forRowAtIndexPath:
como:
- (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];
}
Pero también se llamará cuando una celda que ya se encuentra en la tabla se mueva de la pantalla a la pantalla, por lo que puede no ser exactamente lo que está buscando. Simplemente miré a través de todos los métodos delegados UITableView
y UIScrollView
y no parece haber nada que manejar justo después de insertar una celda de animación.
¿Por qué no simplemente llamar al método que desea que se llame cuando la animación termina después de 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];
}
}
Una posible solución podría ser heredar de UITableView en el que llama a endUpdates
y sobrescribir su setContentSizeMethod
, ya que UITableView ajusta su tamaño de contenido para que coincida con las filas añadidas o eliminadas. Este enfoque también debería funcionar para reloadData
.
Para asegurarse de que se envíe una notificación solo después de endUpdates
, también podría sobrescribir endUpdates
y establecer una endUpdates
allí.
// 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;
}
}
Versión Swift
CATransaction.begin()
CATransaction.setCompletionBlock({
do.something()
})
tableView.beginUpdates()
tableView.endUpdates()
CATransaction.commit()