Siento que esto podría ser un problema común y me preguntaba si había alguna solución común.
Básicamente, mi UITableView tiene alturas de celda dinámicas para cada celda. Si no estoy en la parte superior de UITableView y yo tableView.reloadData()
, el desplazamiento hacia arriba se vuelve nervioso.
Creo que esto se debe al hecho de que debido a que volví a cargar datos, mientras avanzo, el UITableView está recalculando la altura de cada celda que entra en visibilidad. ¿Cómo mitigo eso, o cómo solo recargo Datos desde un IndexPath determinado hasta el final de UITableView?
Además, cuando me las arreglo para desplazarme hasta la parte superior, puedo desplazarme hacia abajo y luego hacia arriba, sin problemas sin saltar. Esto es muy probable porque las alturas UITableViewCell ya se calcularon.
fuente
reloadRowsAtIndexPaths
. Pero (2) ¿qué quiere decir con "saltar" y (3) ha establecido una altura de fila estimada? (Solo trato de averiguar si hay una mejor solución que le permita actualizar la tabla dinámicamente).x
a la última fila en mi TableView ... pero como estoy insertando nuevas filas, no funcionará, no puedo saber cuál será el final de mi vista de tabla antes de volver a cargar los datos.Respuestas:
Para evitar saltos, debe guardar las alturas de las celdas cuando se cargan y dar un valor exacto en
tableView:estimatedHeightForRowAtIndexPath
:Rápido:
C objetivo:
fuente
cellHeightsDictionary
:cellHeightsDictionary = [NSMutableDictionary dictionary];
estimatedHeightForRowAtIndexPath:
devuelve un valor doble puede causar un*** Assertion failure in -[UISectionRowData refreshWithSection:tableView:tableViewRowData:]
error. Para solucionarlo, en sureturn floorf(height.floatValue);
lugar.Versión Swift 3 de respuesta aceptada.
fuente
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
, esto maneja todos los cálculos de altura que necesito.UITableViewDelegate
a mi clase. Es necesario cumplir con ese protocolo porque contiene lawillDisplay
función que se muestra arriba . Espero poder salvar a alguien la misma lucha.El salto se debe a una mala altura estimada. Cuanto más se diferencie el valor estimado de RowHeight de la altura real, más puede saltar la mesa cuando se vuelve a cargar, especialmente cuanto más abajo se haya desplazado. Esto se debe a que el tamaño estimado de la tabla difiere radicalmente de su tamaño real, lo que obliga a la tabla a ajustar su tamaño de contenido y su compensación. Por lo tanto, la altura estimada no debe ser un valor aleatorio sino cercano a lo que crees que va a ser la altura. También he experimentado cuando configuro
UITableViewAutomaticDimension
si sus celdas son del mismo tipo, entoncessi tienes variedad de celdas en diferentes secciones, entonces creo que el mejor lugar es
fuente
tableView(_:estimatedHeightForHeaderInSection:)
La respuesta de @Igor funciona bien en este caso,
Swift-4
código de la misma.en los siguientes métodos de
UITableViewDelegate
fuente
He intentado todas las soluciones anteriores, pero nada funcionó.
Después de pasar horas y pasar por todas las frustraciones posibles, descubrí una manera de solucionar esto. ¡Esta solución es un salvavidas! ¡Trabajado como un encanto!
Swift 4
Lo agregué como una extensión, para que el código se vea más limpio y evitar escribir todas estas líneas cada vez que quiera volver a cargar.
finalmente ..
O bien, podría agregar estas líneas en su
UITableViewCell
awakeFromNib()
métodoy hacer lo normal
reloadData()
fuente
reloadWithoutAnimation
, pero ¿dónde está lareload
parte?tableView.reloadData()
primero y luegotableView.reloadWithoutAnimation()
, aún funciona.Utilizo más formas de solucionarlo:
Para el controlador de vista:
como la extensión para UITableView
El resultado es
fuente
Me encontré con esto hoy y observé:
cellForRowAtIndexPath
no ayuda.La solución fue en realidad bastante simple:
Anule
estimatedHeightForRowAtIndexPath
y asegúrese de que devuelva los valores correctos.Con esto, todos los temblores extraños y saltos en mis UITableViews se han detenido.
NOTA: De hecho, sé el tamaño de mis celdas. Solo hay dos valores posibles. Si las células son realmente de tamaño variable, entonces es posible que desee almacenar en caché el
cell.bounds.size.height
detableView:willDisplayCell:forRowAtIndexPath:
fuente
De hecho, puede volver a cargar solo ciertas filas utilizando
reloadRowsAtIndexPaths
, por ejemplo:Pero, en general, también podría animar los cambios de altura de celda de la tabla de esta manera:
fuente
Aquí hay una versión un poco más corta:
fuente
Reemplazar el método estimadoHeightForRowAtIndexPath con un valor alto, por ejemplo 300f
Esto debería solucionar el problema :)
fuente
Hay un error que creo que se introdujo en iOS11.
Es entonces cuando haces un
reload
tableView quecontentOffSet
se altera inesperadamente. De hechocontentOffset
, no debería cambiar después de una recarga. Tiende a suceder debido a errores de cálculo deUITableViewAutomaticDimension
Debe guardar su
contentOffSet
y restablecerlo a su valor guardado después de que su recarga haya finalizado.¿Cómo lo usas?
Esta respuesta se derivó de aquí
fuente
Este me funcionó en Swift4:
fuente
Ninguna de estas soluciones funcionó para mí. Esto es lo que hice con Swift 4 y Xcode 10.1 ...
En viewDidLoad (), declare la altura de fila dinámica de la tabla y cree las restricciones correctas en las celdas ...
También en viewDidLoad (), registre todas sus puntas de celda tableView en tableview de esta manera:
En tableView heightForRowAt, devuelve una altura igual a la altura de cada celda en indexPath.row ...
Ahora proporcione una altura de fila estimada para cada celda en tableView EstimatedHeightForRowAt. Sé lo más preciso que puedas ...
Eso debería funcionar...
No necesitaba guardar y establecer contentOffset al llamar a tableView.reloadData ()
fuente
Tengo 2 alturas de celda diferentes.
Después de agregar estimadoHeightForRowAt , no hubo más saltos.
fuente
Intenta llamar
cell.layoutSubviews()
antes de devolver el celularfunc cellForRowAtIndexPath(_ indexPath: NSIndexPath) -> UITableViewCell?
. Es un error conocido en iOS8.fuente
Puede usar lo siguiente en
ViewDidLoad()
fuente
Tuve este comportamiento de salto e inicialmente pude mitigarlo estableciendo la altura exacta estimada del encabezado (porque solo tenía 1 vista de encabezado posible), sin embargo, los saltos comenzaron a ocurrir dentro de los encabezados específicamente, sin afectar a toda la tabla.
Siguiendo las respuestas aquí, tuve la idea de que estaba relacionado con las animaciones, por lo que descubrí que la vista de la tabla estaba dentro de una vista de pila, y a veces llamábamos
stackView.layoutIfNeeded()
dentro de un bloque de animación. Mi solución final fue asegurarme de que esta llamada no suceda a menos que sea "realmente" necesaria, porque el diseño "si es necesario" tenía comportamientos visuales en ese contexto, incluso cuando "no era necesario".fuente
Tuve el mismo problema. Tuve paginación y recarga de datos sin animación, pero no ayudó al desplazamiento a evitar saltos. Tengo diferentes tamaños de IPhones, el desplazamiento no estaba nervioso en iphone8 pero sí en iphone7 +
Apliqué los siguientes cambios en la función viewDidLoad :
Y mi problema resuelto. Espero que te ayude a ti también.
fuente
Uno de los enfoques para resolver este problema que encontré es
fuente
En realidad encontré si usas
reloadRows
causando un problema de salto. Entonces deberías intentar usarloreloadSections
así:fuente