Duración de animación de fila UITableView y callback de finalización

¿Hay alguna forma de especificar la duración de las animaciones de fila UITableView o de obtener una callback cuando finaliza la animación?

Lo que me gustaría hacer es actualizar los indicadores de desplazamiento una vez que se completa la animación. Hacer el flash antes no hace nada. Hasta ahora, la solución que tengo es retrasar medio segundo (que parece ser la duración de la animación predeterminada), es decir:

[self.tableView insertRowsAtIndexPaths:newRows withRowAnimation:UITableViewRowAnimationFade]; [self.tableView performSelector:@selector(flashScrollIndicators) withObject:nil afterDelay:0.5]; 

Solo encontré esto. He aquí cómo hacerlo:

C objective

 [CATransaction begin]; [tableView beginUpdates]; [CATransaction setCompletionBlock: ^{ // Code to be executed upon completion }]; [tableView insertRowsAtIndexPaths: indexPaths withRowAnimation: UITableViewRowAnimationAutomatic]; [tableView endUpdates]; [CATransaction commit]; 

Rápido

 CATransaction.begin() tableView.beginUpdates() CATransaction.setCompletionBlock { // Code to be executed upon completion } tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top) tableView.endUpdates() CATransaction.commit() 

Ampliando la buena respuesta de karwag , tenga en cuenta que en iOS 7, el entorno de la CATransaction con una animación UIView ofrece control de la duración de la animación de la tabla.

 [UIView beginAnimations:@"myAnimationId" context:nil]; [UIView setAnimationDuration:10.0]; // Set duration here [CATransaction begin]; [CATransaction setCompletionBlock:^{ NSLog(@"Complete!"); }]; [myTable beginUpdates]; // my table changes [myTable endUpdates]; [CATransaction commit]; [UIView commitAnimations]; 

La duración de la animación de UIView no tiene ningún efecto en iOS 6. Quizás las animaciones de tabla de iOS 7 se implementan de manera diferente, en el nivel de UIView.

Acortando la respuesta correcta de Brent , al menos para iOS 7 puedes envolver todo esto en una llamada [UIView animateWithDuration: delay: options: animations: completion:]:

 [UIView animateWithDuration:10 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{ [self.tableView beginUpdates]; [self.tableView endUpdates]; } completion:^(BOOL finished) { // completion code }]; 

sin embargo, parece que no puedo anular la curva de animación predeterminada de otra cosa que no sea EaseInOut.

Aquí hay una versión Swift de la respuesta de karwag

  CATransaction.begin() tableView.beginUpdates() CATransaction.setCompletionBlock { () -> Void in // your code here } tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top) tableView.endUpdates() CATransaction.commit() 

¡Ese es un gran truco útil! Escribí una extensión UITableView para evitar escribir cosas de CATransaction todo el tiempo.

 import UIKit extension UITableView { /// Perform a series of method calls that insert, delete, or select rows and sections of the table view. /// This is equivalent to a beginUpdates() / endUpdates() sequence, /// with a completion closure when the animation is finished. /// Parameter update: the update operation to perform on the tableView. /// Parameter completion: the completion closure to be executed when the animation is completed. func performUpdate(_ update: ()->Void, completion: (()->Void)?) { CATransaction.begin() CATransaction.setCompletionBlock(completion) // Table View update on row / section beginUpdates() update() endUpdates() CATransaction.commit() } } 

Esto se usa así:

 // Insert in the tableView the section we just added in sections self.tableView.performUpdate({ self.tableView.insertSections([newSectionIndex], with: UITableViewRowAnimation.top) }, completion: { // Scroll to next section let nextSectionIndexPath = IndexPath(row: 0, section: newSectionIndex) self.tableView.scrollToRow(at: nextSectionIndexPath, at: .top, animated: true) }) 

Para mí, necesitaba esto para una collectionView. He hecho una extensión simple para resolver esto:

 extension UICollectionView { func reloadSections(sections: NSIndexSet, completion: () -> Void){ CATransaction.begin() CATransaction.setCompletionBlock(completion) self.reloadSections(sections) CATransaction.commit() } } 

Sustituya tableView -insertRowsAtIndexPaths: e implemente la animación de inserción personalizada / (o la eliminación con su propio método) que desee. No lo intenté yo solo sin embargo.

Podría tratar de ajustar el insertRowsAtIndexPath en una

 - (void)beginUpdates - (void)endUpdates 

transacción, luego haga el flash después.