Altura del marco UITableViewCell no coincidente tableView: heightForRowAtIndexPath:

Estoy construyendo un UITableView con celdas de tabla personalizadas de altura variable, su altura determinada por el tamaño de una UILabel contenida de varias líneas. Tengo el tableView:heightForRowAtIndexPath: delegate cableado y calculo la altura final correctamente usando sizeWithFont:constrainedToSize:

Me he encontrado con un problema extraño tableView:cellForRowAtIndexPath: se llama al método fuente 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 pnetworkingeterminada de la vista de tabla (86 px, como lo he configurado en Interface Builder, la altura correcta cuando la UILabel contenida tiene una sola línea de text), en lugar de ser la altura que tableView:heightForRowAtIndexPath: determinado correcto para esa ruta de índice.

Estoy produciendo las celdas en cellForRowAtIndexPath: usando dequeuing, 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, entonces, que sea lo que sea que iOS esté haciendo detrás de escena, la dequeuing no está configurando la propiedad de marco de la celda para que coincida con la altura calculada. Esto en sí mismo no es tan sorprendente, ya que deja de preocuparse por las instancias celulares, no por su geometry. Sin embargo, las celdas se representan correctamente, por lo que la propiedad de altura se establece en alguna parte , pero sucede después de cellForRowAtIndexPath:

Por lo tanto: cuando inicialmente cell.frame.size.height vista de tabla, cell.frame.size.height es 86 para todas las celdas tal como aparecen por primera vez cuando desploop la list hacia abajo. Dado que la geometry correcta se establece un poco después del primer cellForRowAtIndexPath: para cada fila antes de que se muestre, cuando vuelvo a upload, la propiedad de altura es correcta para cada celda que vuelve a verse 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 desde ese punto.

¿Cuál es la forma correcta de get la altura correcta de la celda la primera vez, antes de que ocurra una reutilización basada en la eliminación de la queue? Necesito esto para hacer un poco de reposicionamiento de las subvistas de la celda de la tabla. ¿Debo llamar manualmente a heightForRowAtIndexPath: en cellForRowAtIndexPath: y luego configurar manualmente el marco de la instancia CustomCell recién creada para que coincida con esa altura? Esto parece networkingundante, y tendría que crear un mecanismo para detectar cuándo se crea la celda por primera vez con la altura incorrecta del marco frente a cuando se laque con la altura correcta del cuadro más adelante para evitar esta networkingundancia.

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

Como lo sugirió Flexo, responder esto 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 get el marco correcto en la tableView:willDisplayCell:forRowAtIndexPath: método de UITableViewDelegate , por lo que es el lugar correcto para realizar la personalización de la subvista que se basa en el marco correcto que se establece, no en cellForRowAtIndexPath: .

Interesante que los docs digan esto, sin embargo:

Después de que el delegate regrese, la vista de tabla establece solo las properties de alpha y frame , y solo cuando se animan filas a medida que se deslizan hacia adentro o hacia afuera.

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

No olvide que la celda es una vista UIView , por lo que la layoutSubviews es también una forma válida de get el marco correcto y ajustar el tamaño / position de las sublists. Simplemente no olvides llamar a [super layoutSubviews] .

La forma más fácil que encontré fue llamar a cell.layoutIfNeeded() antes de hacer cualquier configuration en la celda. Esto asegura que todas las restricciones de layout se calculen y que los frameworks estén configurados.