Estou implementando cabeçalhos de seção recolhíveis em um UITableViewController.
Veja como eu determino quantas linhas mostrar por seção:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.sections[section].isCollapsed ? 0 : self.sections[section].items.count
}
Existe uma estrutura que mantém as informações da seção com um booleano para 'isCollapsed'.
Veja como estou alternando seus 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()
}
Tudo está funcionando e animando muito bem, no entanto, no console ao recolher uma seção expandida, recebo o seguinte [Assert]:
[Assert] Não foi possível determinar o novo índice de linha global para preReloadFirstVisibleRow (0)
Isso acontece, independentemente de ser a mesma seção aberta, fechar (fechar) ou se estou abrindo outra seção e 'fechando automaticamente' a seção aberta anteriormente.
Não estou fazendo nada com os dados; isso é persistente.
Alguém poderia ajudar a explicar o que está faltando? obrigado
fonte
Respostas:
Para que um tableView saiba onde está enquanto recarrega as linhas, etc, ele tenta encontrar uma "linha âncora" que ele usa como referência. Isso é chamado de
preReloadFirstVisibleRow
. Como esse tableView pode não ter nenhuma linha visível em algum momento devido a todas as seções serem recolhidas, o tableView ficará confuso, pois não consegue encontrar uma âncora. Ele será redefinido para o topo.Solução: adicione uma linha de altura 0 a cada grupo que foi recolhido. Dessa forma, mesmo que uma seção seja recolhida, ainda há uma linha presente (embora com 0px de altura). O tableView sempre tem algo para se conectar como referência. Você verá isso com efeito, adicionando uma linha
numberOfRowsInSection
se o número de linhas for 0 e lidando com outrasindexPath.row
chamadas, certificando-se de retornar o valor da célula phatom antes queindexPath.row
seja necessário sedatasource.visibleRows
for 0.É mais fácil fazer uma demonstração no código:
fonte