Extraño UITableView insert / eliminar animation de fila

Estoy viendo un efecto extraño al insert / eliminar un UITableViewCell en un UITableView con animation (UITableViewRowAnimationTop).

La falla de animation ocurre cuando la celda que se inserta es mucho más grande que la celda de arriba.

Este video muestra la falla en el simulador, la celda amarilla aparece de repente fuera de cualquier lugar cuando se supone que debe deslizarse desde la parte superior.

Aquí está el proyecto Xcode del video.

Bellow es el código de inserción / animation de la celda.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 2 + self.thirdCellVisible; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; if (indexPath.row == 1) { if (self.thirdCellVisible) { self.thirdCellVisible = !self.thirdCellVisible; [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; } else { self.thirdCellVisible = !self.thirdCellVisible; [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; } } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == self.thirdCellIndexPath.row) { return 100.0f; } return 44.0f; } 

Tendrás que llamar

 [tableView beginUpdates] 

y

 [tableView endUpdates] 

antes y después de llamar a insert / eliminar methods como se muestra a continuación:

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 2 + self.thirdCellVisible; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; if (indexPath.row == 1) { if (self.thirdCellVisible) { self.thirdCellVisible = !self.thirdCellVisible; [self.tableView beginUpdates]; [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; } else { self.thirdCellVisible = !self.thirdCellVisible; [self.tableView beginUpdates]; [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; } } } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == self.thirdCellIndexPath.row) { return 100.0f; } return 44.0f; } 

De acuerdo con Apple aquí :

Para animar una inserción, eliminación y recarga por lotes de filas y secciones, llame a los methods correspondientes dentro de un bloque de animation definido por sucesivas llamadas a beginUpdates y endUpdates. Si no llama a los methods de inserción, eliminación y recarga dentro de este bloque, los índices de fila y sección pueden ser inválidos. Las llamadas a beginUpdates y endUpdates pueden anidarse; todos los índices se tratan como si solo hubiera un bloque de actualización externo.

Al final de un bloque, es decir, después de que devuelve endUpdates, la vista de tabla consulta su origen de datos y delega como de costumbre para los datos de fila y sección. Por lo tanto, los objects de colección que respaldan la vista de tabla deben actualizarse para reflejar las filas o secciones nuevas o eliminadas.

Tendrá que llamar a [tableView beginUpdates] y [tableView endUpdates] antes y después de llamar a los methods de inserción / eliminación, respectivamente.

Apple proporciona un ejemplo en el enlace anterior.

Nota : Si los elementos de la vista de la matriz y de la tabla no están sincronizados, sin las llamadas de inicio / fin se generará una exception.

Sugerencia : intente primero withRowAnimation:UITableViewRowAnimationAutomatic

Use [tableView beginUpdates] y [tableView endUpdates] como sigue

  - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; if (indexPath.row == 1) { if (self.thirdCellVisible) { self.thirdCellVisible = !self.thirdCellVisible; [self.tableView beginUpdates]; [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; } else { self.thirdCellVisible = !self.thirdCellVisible; [self.tableView beginUpdates]; [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; [self.tableView endUpdates]; } } } 

Aquí está el enlace de video de mi código de trabajo: https://dl.dropboxusercontent.com/u/30316681/480.mov

A continuación se muestra mi código de trabajo:

 @interface ViewController () @property (nonatomic, readwrite) BOOL thirdCellVisible; @property (nonatomic, strong) NSIndexPath *thirdCellIndexPath; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; self.thirdCellIndexPath = [NSIndexPath indexPathForRow:2 inSection:0]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 2 + self.thirdCellVisible; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == self.thirdCellIndexPath.row) { return 100.0f; } return 44.0f; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; if (indexPath.row == 1) { if (self.thirdCellVisible) { self.thirdCellVisible = !self.thirdCellVisible; [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; } else { self.thirdCellVisible = !self.thirdCellVisible; [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath] withRowAnimation:UITableViewRowAnimationTop]; } } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellId = @"id"; UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:cellId]; if(cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId]; } NSString *cellTitle = [NSString stringWithFormat:@"Cell %ld", (long)indexPath.row]; cell.textLabel.text = cellTitle; if(indexPath.row == 2) cell.backgroundColor = [UIColor yellowColor]; else cell.backgroundColor = [UIColor clearColor]; return cell; } @end