6

Estoy construyendo un UITableView con celdas de tabla de altura variable, su altura determinada por el tamaño de una UILabel contenida de varias líneas. Tengo el método de delegado tableView:heightForRowAtIndexPath: cableado y el cálculo de la altura final correctamente utilizando sizeWithFont:constrainedToSize:.UITableViewCell altura de cuadro que no coincide tableView: heightForRowAtIndexPath:

He tropezado con un problema extraño: cuando se llama al método de origen de datos tableView:cellForRowAtIndexPath:, la altura correcta por fila ya se ha determinado como se describió anteriormente, pero el marco de la celda no coincide con esa altura. En cambio, la propiedad frame.size.height de la celda es la altura de celda predeterminada de la vista de tabla (86 px, como lo configuré en Interface Builder, la altura correcta cuando UILabel contiene solo una línea de texto), en lugar de ser la altura que tableView:heightForRowAtIndexPath: determinó correcta para esa ruta de índice.

estoy produciendo las células en cellForRowAtIndexPath: usando desencola, es decir,

// Using storyboards, this never returns nil, no need to check for it 
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:@"SomeIdentifier"]; 
NSLog(@"%f", cell.frame.size.height); // 86, not correct if the cell contains a multi-line UILabel 

Parece, pues, que todo lo que iOS está haciendo detrás de las escenas, la desencola no está estableciendo la propiedad del marco de la célula para que coincida con la altura calculada. Esto en sí mismo no es tan sorprendente, ya que la eliminación de preocupaciones se centra en instancias de células, no en su geometría. Sin embargo, las celdas se representan correctamente, por lo que la propiedad de altura se establece en en algún lugar, pero ocurre después de cellForRowAtIndexPath:.

Por lo tanto, cuando llene inicialmente la vista de tabla, cell.frame.size.height es 86 para todas las celdas tal como aparecen por primera vez cuando desplazo la lista hacia abajo. Dado que la geometría correcta se establece en algún momento después del primer cellForRowAtIndexPath: para cada fila antes de que se muestre, cuando me desplazo hacia atrás, la propiedad de altura es correcta para cada celda que vuelve a la vista después de ser reutilizada.

Después de esto puedo desplazar la vista de tabla hacia adelante y hacia atrás a voluntad, y la propiedad de altura permanece correcta para cada celda a partir de ese momento.

¿Cuál es la forma correcta de obtener la altura de celda correcta la primera vez, antes de que ocurra una reutilización basada en deque? Necesito esto para hacer un poco de reposicionamiento de las subvistas de la celda de la tabla. ¿Debo llamar manualmente al heightForRowAtIndexPath: en cellForRowAtIndexPath: y luego configurar manualmente el marco de la instancia CustomCell recientemente creada para que coincida con esa altura? Esto parece redundante, y necesitaría crear un mecanismo para detectar cuándo se crea la celda por primera vez con una altura de fotograma incorrecta frente a cuando se quita la cola con la altura de fotograma correcta más tarde para evitar esta redundancia.

Por lo tanto, si alguien puede arrojar algo de luz sobre la lógica detrás de esto, lo agradecería.

Respuesta

6

Según lo sugerido por Flexo, responder esto yo mismo es aparentemente mejor que agregar una edición a la pregunta. Entonces, aquí está la edición anterior como respuesta:


No importa, debería leer los documentos mejor. Puedo obtener el fotograma correcto en el método tableView:willDisplayCell:forRowAtIndexPath: de UITableViewDelegate, por lo que es el lugar correcto para realizar la personalización de la subvista que se basa en el fotograma correcto que se está configurando, no en cellForRowAtIndexPath:.

Es interesante que los documentos dicen que esto, sin embargo:

Después de las declaraciones de delegate, la vista tabla muestra sólo los alpha y frame propiedades, y sólo cuando la animación de filas mientras se deslizan dentro o hacia fuera.

... ya que el cuadro correcto ya está allí cuando se llama a este método delegado. Pero de todos modos, problema resuelto.

+0

la pregunta inicial es realmente buena, pero esta respuesta no es muy buena. ¿Te importa compartir cómo resolviste el problema? – botbot

0

No olvide que la celda es UIView, por lo que anular layoutSubviews también es una forma válida de obtener el marco correcto y ajustar el tamaño/posición de las subvistas. No olvides llamar al [super layoutSubviews].

0

La manera más fácil que encontré fue simplemente llamar al cell.layoutIfNeeded() antes de realizar cualquier configuración en la celda. Esto asegura que todas las restricciones de diseño se calculan y los marcos se establecen.

Cuestiones relacionadas