El marco de la vista del encabezado cambió para siempre después de la eliminación de la sección UITableView

Estoy reutilizando los encabezados, manteniéndolos en el dictionary donde el número de sección es key y la vista de encabezado es valor.

Después de que animé una sección eliminada y volví a cargar otra, las vistas de cabecera de solo estas secciones "desaparecieron". Después de algunas búsquedas, encontré que los frameworks de esta vista de encabezado se cambiaron. Frame.X de la vista de encabezado de la sección que se eliminó con desplazador UITableViewRowAnimationRight a la derecha por ancho de pantalla (320) y el que se volvió a UITableViewRowAnimationAutomatic con UITableViewRowAnimationAutomatic desplazado por Y

¡El problema principal y la confusión provienen del hecho de que no puedo cambiar estos frameworks! Bueno, cambian al principio, pero nada cambia visualmente y en la otra llamada de viewForHeaderInSection: cuadros se cambian nuevamente.

Así es como hago eso:

Supongamos que tenemos 3 secciones, con los datos de cada uno en una de las matrices _first , _second y _third . Y pulsando touchupinside llamamos a handleTouchUp: ( _second permanece sin cambios)

 - (void) handleTouchUp: (UIButton *)sender { if ([_first count] == 0) { sectionCount = 3; _first = [NSMutableArray arrayWithObjects: @"First 1", @"First 2", nil]; _third = [NSMutableArray arrayWithObjects: @"Third 1", @"Third 2", @"Third 3", @"Third 4", @"Third 5", nil]; [tableView reloadData]; } else { sectionCount = 2; [_first removeAllObjects]; _third = [NSMutableArray arrayWithObjects: @"First 1", @"First 2", @"Third 1", @"Third 2", @"Third 3", @"Third 4", @"Third 5", nil]; [tableView beginUpdates]; [tableView deleteSections: [NSIndexSet indexSetWithIndex: 0] withRowAnimation:UITableViewRowAnimationRight]; [tableView reloadSections: [NSIndexSet indexSetWithIndex: 2] withRowAnimation:UITableViewRowAnimationAutomatic]; [tableView endUpdates]; } } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { NSNumber *key = [NSNumber numberWithInteger: section]; UIView *header = [_headers objectForKey: key]; if (header) { } else { header = [[UIView alloc] init]; switch (section) { //Doing something with header here (eg set background color) } [_headers setObject:header forKey: key]; } [header setFrame: CGRectMake(0, 0, 320, 25)]; return header; } 

Aquí está el código completo de ViewController.m y el proyecto de testing

ACTUALIZACIÓN: Puede haber otros errores en el proyecto, pero no es importante: es un proyecto de testing. El único problema importante son las vistas de encabezado no válidas. Eliminar la vista inválida y crear la nueva no es la solución: mata el punto de reutilizar vistas de encabezado.

Encontré varios errores en su proyecto que en realidad provocaron algunos lockings y creo que también fueron responsables de los errores de vista de encabezado que estaba viendo en la aplicación. Después de arreglarlos y la aplicación parece funcionar correctamente para mí.

Aquí hay una versión actualizada de su proyecto: https://bitbucket.org/reydan/tableheaderviews

Traté de mantenerlo lo más similar posible a su proyecto inicial, pero tuve que hacer algunos cambios. Si crees que no coincide con tu funcionalidad deseada, deja un comentario y actualizaré (Esto es lo que deduje que el proyecto debe comportarse como). Todos los cambios que se explican a continuación también se pueden ver en este proyecto actualizado.

Los problemas que encontré estaban relacionados con el hecho de que si borras una sección de una vista de tabla, toda la sección después de ella tendrá su índice cambiado (con -1). Esto es normal, porque el índice de sección es realmente un índice y no una key única asignada a cada sección.

Después de eliminar la primera sección, la tercera sección ahora tenía índice = 1 y los methods delegates de vista de tabla leen datos incorrectamente (incluidas las vistas de encabezado), ya que tenía todo lo que se basaba en el índice de la sección.

Para solucionarlo, cambié el caching de la vista del encabezado para usar las matrices de datos como keys (_primero, _segundo o _ tercera). Para facilitar esto, he creado un método que puede llamar desde varios lugares y devuelve la matriz de datos correcta en function del índice de sección y el recuento de sección actual:

 - (NSArray*)dataArrayForSection:(NSInteger)section { if (sectionCount == 3) { switch (section) { case 0: return _first; case 1: return _second; case 2: return _third; } } else { switch (section) { case 0: return _second; case 1: return _third; } } return nil; } 

Ahora que la memory caching del encabezado usa las matrices de datos como keys, es importante eliminar las inputs del encabezado al reasignar las matrices en el método handleTouchUp .

 - (void) handleTouchUp: (UIButton *)sender { NSLog(@"Touched!"); if ([_first count] == 0) { sectionCount = 3; // **INSERTED** Removes the cache for the _first and _third keys because you are recreating the arrays again, // and so you are losing the initial key. Not doing this, results in a memory leak [_headers removeObjectForKey:_first]; [_headers removeObjectForKey:_third]; _first = [NSMutableArray arrayWithObjects: @"First 1", @"First 2", nil]; _third = [NSMutableArray arrayWithObjects: @"Third 1", @"Third 2", @"Third 3", @"Third 4", @"Third 5", nil]; [tableView reloadData]; // [tableView beginUpdates]; // [tableView reloadSections: [NSIndexSet indexSetWithIndex: 0] withRowAnimation:UITableViewRowAnimationRight]; // [tableView reloadSections: [NSIndexSet indexSetWithIndex: 2] withRowAnimation:UITableViewRowAnimationAutomatic]; // [tableView endUpdates]; } else 

Otra cosa que mejoré es la reutilización de las celdas de vista de tabla. Siempre debe intentar y reutilizar UITableViewCells existente (con pocas excepciones). El cellForRowAtIndexPath ahora se ve así:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSArray* dataarray = [self dataArrayForSection:indexPath.section]; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"my_text_cell"]; if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"my_text_cell"]; if (dataarray == nil) cell.textLabel.text = @"default"; else cell.textLabel.text = [dataarray objectAtIndex:indexPath.row]; return cell; } 

Si tiene alguna pregunta, deje un comentario.

EDITAR

Traté de actualizar mi proyecto de testing cuando lo solicitó, para mantener el caching intacto y de hecho pude reproducir el error: después de la animation de borrado / recarga, el encabezado de la última sección no está visible.

Lo que descubrí es que la animation de recarga automática que iOS elige es la animation Fade. Esto hace que la vista del encabezado se desvanezca. Lo probé agregando otro button en la aplicación que establece alpha = 1 para todas las vistas del encabezado en caching. Después de la animation de recarga, presioné este button y las vistas del encabezado aparecieron correctamente.

Intenté usar otras animaciones, pero no se veían bien.

Al final, no creo que Apple recomiende las vistas de encabezado de caching. En la documentation, a partir de iOS 6.0 hay un nuevo método que soluciona este problema. Se comporta de forma similar a eliminar celdas, pero para vistas de encabezado / pie de página
- (id)dequeueReusableHeaderFooterViewWithIdentifier:(NSString *)identifier

Por lo tanto, si apunta a iOS 6.0+, puede usar esto en lugar de almacenar en caching manualmente los encabezados. De lo contrario, la solución que encontré es eliminar del caching solo las vistas del encabezado para las secciones eliminadas y recargadas (_primera y _ tercera).

Actualicé el proyecto para eliminar solo el último encabezado de sección al actualizar