Expanda UILabel dentro de UITableView con el botón “más”, como Instagram

Tengo un proyecto (que ha sido escrito por otras personas) donde hay un feed con contenido y texto que se muestran dentro de una vista de tabla. Cada publicación corresponde a una sección en la vista de tabla, y cada sección tiene sus propias filas correspondientes a elementos como contenido, texto, botón similar, etc.

Necesito mostrar una etiqueta corta para títulos de publicaciones con un botón “más” dentro de la celda de vista de tabla, y cuando se toque más botón, la etiqueta se expandirá al tamaño que corresponda, todo sucede dentro de una celda de vista de tabla. Cuando se toca el botón más, cambio la propiedad numberOfLines la etiqueta a cero, y como las celdas tienen una altura automática, todo lo que necesito es volver a cargar esa celda de subtítulos en particular. (la celda se muestra correctamente con el tamaño expandido si configuro numberOfLines en 0 en el primer lugar antes de mostrar la celda).

He intentado:

[tableView beginUpdates]; tableView endUpdates];

He intentado varias opciones de animación con:

[tableView reloadRowsAtIndexPaths:@[myPath] withRowAnimation:UITableViewRowAnimation(Bottom,Top,None etc)];

He intentado:

[tableView reloadSections:[NSIndexSet indexSetWithIndex:myPath.section] withRowAnimation:UITableViewRowAnimation(Top,Bottom,None etc)];

Pero todos producen el mismo resultado: todo el diseño de la vista de tabla se arruina: salta a otra celda, algunas vistas se ponen en blanco, las células se superponen, el video dentro de las celdas deja de reproducirse y la etiqueta no se expande (pero se refresca dentro en sí, por ejemplo, ese breve texto de vista previa con una línea se anima desde arriba / abajo, etc., pero no se expande).

¿Qué podría estar causando el desastre de toda la vista de tabla y cómo puedo volver a cargar solo una celda correctamente con la animación de expansión, sin estropear todo el diseño? He visto muchas preguntas y respuestas sobre esto, pero todas recomiendan las opciones que ya he probado y explicado anteriormente.

Mi aplicación está dirigida a iOS 8.0+

ACTUALIZACIÓN: Aquí está el código relevante (con algunas partes relacionadas con el funcionamiento interno que no están relacionadas con el diseño, eliminadas):

 MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier: MyCellIdentifier forIndexPath:indexPath]; cell.delegate = self; cell.indexPathToReloadOnAnimation = indexPath; cell.shouldShortenCaption = YES; id post = self.posts[indexPath.section] ; [cell setPost:post]; return cell; 

Y dentro setPost: :

 if(self.shouldShortenCaption){ captionLabel.numberOfLines = 2; }else{ captionLabel.numberOfLines = 0; } NSString *text = [some calculated (deterministic) text from post object]; 

La acción del botón es simple:

 self.shouldShortenCaption = NO; [one of the reload codes that I've written above in the question] 

ACTUALIZACIÓN 2: Aquí hay algunos métodos más con respecto al problema:

 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { if (section < self.posts.count) { return 59; }else return 0; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { if (section < self.posts.count) { MyFeedHeader *header = [tableView dequeueReusableCellWithIdentifier:MyFeedHeaderIdentifier]; header.delegate = self; [header setPostIndex:section]; [header setPost:self.posts[section]] ; return header; } else return nil; } 

El método setPost: del setPost: básicamente establece los textos relevantes en las tags (que no tienen nada que ver con el título, son células completamente diferentes. La celda problemática no es la celda del encabezado). La tabla no tiene ningún método de pie de página. El único método con respecto a la altura es el de arriba.

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section >= self.posts.count) { return 1; } id post = self.posts[section]; [calculate number of rows, which is deterministic] return [number of rows]; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { BOOL hasCursor = self.cursor && self.hasMore ? 1 : 0; return self.posts.count + hasCursor; } 

(Contador de correos y cursor y hasMore también son deterministas).

ACTUALIZACIÓN 3: He hecho una pregunta (que no era un duplicado, aunque hay preguntas similares) y obtuve una respuesta útil que resolvió mi problema. ¿Pueden los downvoters explicar por qué han votado negativamente?

Aquí hay un ejemplo: https://github.com/DonMag/DynamicCellHeight

La Tabla B es una forma de lograr “Más / Menos” (la Tabla A era para otro diseño con el que jugué). Utiliza [tableView beginUpdates]; tableView endUpdates]; [tableView beginUpdates]; tableView endUpdates]; método de desencadenar el redistribución de la tabla.

La clave es configurar todas las restricciones configuradas correctamente, por lo que el motor de diseño automático hace lo que espera.

El ejemplo está en Swift, pero debería traducirse fácilmente a Obj-C (creo que lo hice en Obj-C primero).

enter image description here

Editar: algunas notas adicionales …

Esto está utilizando un método bastante estándar de celdas de vista de tabla de altura dinámica. Las restricciones espaciales verticales entre elementos efectivamente “empujan” los límites de la celda. El toque aquí alterna la propiedad numberOfLines de la etiqueta entre 2 y 0 (cero significa tantas líneas como sea necesario). Las llamadas secuenciales a beginUpdates / endUpdates en la vista de tabla endUpdates al motor de diseño automático que vuelva a calcular las alturas de fila sin necesidad de volver a cargar los datos.

Para este ejemplo, UIView un pequeño “truco” para obtener el efecto de expansión / colapso sin problemas … La etiqueta de UIView que ve aquí está contenida en una UIView (con clipsToBounds verdadero). Hay una segunda etiqueta multilínea duplicada (alfa 0 por lo que no es visible) que controla la altura. Descubrí que al cambiar numberOfLines en la etiqueta visible se “ajusta” a 2 líneas, y luego se produce la animación de cambio de tamaño … lo que provoca que el texto “salte”.

Solo por el gusto de hacerlo, agregué la versión “no tan buena” a mi repository de GitHub en aras de la comparación.

enter image description here