Animación al insert una fila más grande en una UITableView suponiendo una altura incorrecta

Tengo un problema al animar la adición o eliminación de una fila en un UITableView que tiene una altura diferente a la de otras filas.

Los siguientes gifs demuestran el problema con las filas de la altura pnetworkingeterminada (44pts) y una fila más grande (100pts) siendo insertada y eliminada. El de la izquierda es una pantalla de grabación del simulador (la nueva celda que termina cubriendo la fila cinco es un problema diferente) y la de la derecha es una maqueta de lo que debería hacer.

GIF de tema de animaciónGIF de cómo debería verse

En mi caso, tengo un montón de filas, cada 60pts de altura. Cuando se toca un button en la celda, una celda de "edición" se deslizará desde abajo, empujando las celdas inferiores hacia abajo. Esta celda de edición tiene una altura de 180pts. Cuando insertRowsAtIndexPaths:withRowAnimation: o deleteRowsAtIndexPaths:withRowAnimation: la animation asume la altura equivocada de 60pts, en lugar de los 180pts, debería ser
Esto significa que en el caso de UITableViewRowAnimationTop la nueva celda aparece a -60pts desde la position en la que terminará y se desliza hacia abajo hasta su nueva position; alnetworkingedor de un tercio de la animation que debería estar haciendo. Mientras tanto, la siguiente fila anima suavemente desde su position inicial a 180pts hacia abajo, exactamente como debería.

¿Alguien ha encontrado una solución real para esto? alguna manera de decirle a la nueva fila qué altura se supone que debe ser para la animation?

A continuación se muestra el código que utilizo para ocultar y mostrar la fila de edición. Estoy usando una TLSwipeForOptionsCell para activar la edición, pero se replica fácilmente usando, por ejemplo, tableView:didSelectRowAtIndexPath:

 -(void)hideEditFields{ [self.tableView beginUpdates]; [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForItem:editFormVisibleForRow+1 inSection:0]] withRowAnimation:UITableViewRowAnimationTop]; editFormVisibleForRow = -1; [self.tableView endUpdates]; } -(void)cellDidSelectMore:(TLSwipeForOptionsCell *)cell{ NSIndexPath* indexPath = [self.tableView indexPathForCell:cell]; // do nothing if this is the currently selected row if(editFormVisibleForRow != indexPath.row){ if(editFormVisibleForRow >= 0){ [self hideEditFields]; // update the index path, as the cell positions (may) have changed indexPath = [self.tableView indexPathForCell:cell]; } [self.tableView beginUpdates]; editFormVisibleForRow = indexPath.row; [self.tableView insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForItem:editFormVisibleForRow+1 inSection:0] ] withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; } } -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return _dataSource.count + (editFormVisibleForRow >= 0 ? 1 : 0); } -(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ int row = indexPath.row; if(editFormVisibleForRow >= 0 && row > editFormVisibleForRow && row <= editFormVisibleForRow + 1){ return 180.0f; } else return 60.0; } 

Hurgando un poco, parece que este es un problema común sin una respuesta clara. La mayoría de las preguntas similares que he encontrado aquí en SO están sin respuesta u ofrecen soluciones específicas a la situación del solicitante. (ejemplos: problema con RowAnimation , altura UITableViewCell personalizada produce una animation incorrecta , falla de animation UITableView al eliminar e insert celdas con diferentes alturas ).

Además, en lugar de tratar de hacer una fila de edición de tamaño triple, traté de hacer tres filas más pequeñas y animarlas, pero esto no fue adecuado porque aparecieron todas al mismo time. También traté de animarlos uno tras otro, pero la relajación hizo que parezca extraño, con una evidente animation de 3 pasos, en lugar de que toda la vista de edición se deslice fuera de la vista en un solo movimiento.

Edit: Acabo de reloadRowsAtIndexPaths:withRowAnimation: UITableViewRowAnimationNone count de que si llamo a reloadRowsAtIndexPaths:withRowAnimation: UITableViewRowAnimationNone para la fila encima de la que estoy tratando de animar, cambia el comportamiento de la animation; a saber, la animation supone que la altura es 0pts, como se demuestra en la siguiente animation. Está más cerca de lo que quiero, pero aún así no es correcto, ya que la velocidad de animation es incorrecta y deja un espacio (en mi aplicación esto significa que el color de background se mueve)

GIF de problema con la fila anterior recargada

Esto, usando didSelectRowAtIndexPath funcionó para mí:

 @interface TableController () @property (strong,nonatomic) NSArray *theData; @property (strong,nonatomic) NSIndexPath *pathToEditCell; @end @implementation TableController - (void)viewDidLoad { [super viewDidLoad]; self.theData = @[@"One",@"Two",@"Three",@"Four",@"Five",@"Six",@"Seven",@"Eight",@"Nine"]; [self.tableView reloadData]; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return ([indexPath isEqual:self.pathToEditCell])? 100: 44; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return (self.pathToEditCell == nil)? self.theData.count: self.theData.count + 1; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if ([indexPath isEqual:self.pathToEditCell]) { RDEditCell *cell = [tableView dequeueReusableCellWithIdentifier:@"EditCell" forIndexPath:indexPath]; return cell; }else{ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; cell.textLabel.text = self.theData[indexPath.row]; return cell; } } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ if (self.pathToEditCell == nil) { // first time selecting a row self.pathToEditCell = [NSIndexPath indexPathForRow:indexPath.row +1 inSection:indexPath.section]; [self.tableView insertRowsAtIndexPaths:@[self.pathToEditCell] withRowAnimation:UITableViewRowAnimationAutomatic]; }else if ([self.pathToEditCell isEqual:indexPath]){ // deletes the edit cell if you click on it self.pathToEditCell = nil; [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; }else{ // close the old edit cell and adds another if you click on another cell while the edit cell is on screen [self.tableView beginUpdates]; [self.tableView deleteRowsAtIndexPaths:@[self.pathToEditCell] withRowAnimation:UITableViewRowAnimationFade]; self.pathToEditCell = indexPath; [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; [self.tableView endUpdates]; } } 

Para las eliminaciones, me gusta la apariencia de la opción "fundido" para la animation, pero "superior" también estaba bien.