Estoy implementando encabezados de sección plegables en un UITableViewController.
Así es como determino cuántas filas mostrar por sección:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.sections[section].isCollapsed ? 0 : self.sections[section].items.count
}
Hay una estructura que contiene la información de la sección con un bool para 'isCollapsed'.
Así es como estoy alternando sus estados:
private func getSectionsNeedReload(_ section: Int) -> [Int]
{
var sectionsToReload: [Int] = [section]
let toggleSelectedSection = !sections[section].isCollapsed
// Toggle collapse
self.sections[section].isCollapsed = toggleSelectedSection
if self.previouslyOpenSection != -1 && section != self.previouslyOpenSection
{
self.sections[self.previouslyOpenSection].isCollapsed = !self.sections[self.previouslyOpenSection].isCollapsed
sectionsToReload.append(self.previouslyOpenSection)
self.previouslyOpenSection = section
}
else if section == self.previouslyOpenSection
{
self.previouslyOpenSection = -1
}
else
{
self.previouslyOpenSection = section
}
return sectionsToReload
}
internal func toggleSection(_ header: CollapsibleTableViewHeader, section: Int)
{
let sectionsNeedReload = getSectionsNeedReload(section)
self.tableView.beginUpdates()
self.tableView.reloadSections(IndexSet(sectionsNeedReload), with: .automatic)
self.tableView.endUpdates()
}
Todo funciona y se anima muy bien, sin embargo, en la consola al colapsar una sección expandida, obtengo esto [Afirmar]:
[Afirmar] No se puede determinar el nuevo índice de fila global para preReloadFirstVisibleRow (0)
Esto sucede, independientemente de si es la misma Sección abierta, cerrando (colapsando), o si estoy abriendo otra sección y 'cerrando automáticamente' la sección abierta anteriormente.
No estoy haciendo nada con los datos; Eso es persistente.
¿Alguien podría ayudar a explicar lo que falta? Gracias
fuente
Respuestas:
Para que un TableView sepa dónde está mientras está recargando filas, etc., intenta encontrar una "fila de anclaje" que utiliza como referencia. Esto se llama a
preReloadFirstVisibleRow
. Dado que esta tabla de vista puede no tener filas visibles en algún momento debido a que todas las secciones están colapsadas, la tabla de vista se confundirá ya que no puede encontrar un ancla. Luego se restablecerá a la parte superior.Solución: agregue una fila de altura 0 a cada grupo que esté contraído. De esa manera, incluso si una sección se contrae, todavía hay una fila presente (aunque de 0px de altura). El tableView siempre tiene algo para enganchar como referencia. Verá esto en efecto agregando una fila
numberOfRowsInSection
si el número de filas es 0 y manejando cualquierindexPath.row
llamada adicional asegurándose de devolver el valor de celda falso antes de queindexPath.row
sea necesario si eldatasource.visibleRows
es 0.Es más fácil hacer una demostración en código:
fuente