J'implémente des en-têtes de section réductibles dans un UITableViewController.
Voici comment je détermine le nombre de lignes à afficher par section:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.sections[section].isCollapsed ? 0 : self.sections[section].items.count
}
Il y a une structure qui contient les informations de section avec un booléen pour 'isCollapsed'.
Voici comment je change leurs états:
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()
}
Tout fonctionne et s'anime bien, mais dans la console lors de la réduction d'une section développée, j'obtiens ceci [Assert]:
[Assert] Impossible de déterminer le nouvel index de ligne global pour preReloadFirstVisibleRow (0)
Cela se produit, qu'il s'agisse de la même section ouverte, de la fermeture (repli) ou si j'ouvre une autre section et que je ferme automatiquement la section précédemment ouverte.
Je ne fais rien avec les données; c'est persistant.
Quelqu'un pourrait-il aider à expliquer ce qui manque? Merci
la source
Réponses:
Pour qu'une tableView sache où elle se trouve lorsqu'elle recharge des lignes, etc., elle essaie de trouver une "ligne d'ancrage" qu'elle utilise comme référence. C'est ce qu'on appelle un
preReloadFirstVisibleRow
. Étant donné que cette tableView peut ne pas avoir de lignes visibles à un moment donné en raison de la réduction de toutes les sections, la tableView sera confuse car elle ne peut pas trouver d'ancre. Il sera ensuite réinitialisé au sommet.Solution: ajoutez une ligne de hauteur 0 à chaque groupe réduit. De cette façon, même si une section est réduite, il y a toujours une ligne présente (bien que de 0px de hauteur). La tableView a alors toujours quelque chose à laquelle se connecter comme référence. Vous verrez cela en effet par l'ajout d'une ligne
numberOfRowsInSection
si le nombre de lignes est 0 et la gestion de tout autreindexPath.row
appel en vous assurant de renvoyer la valeur de la cellule phatom avantindexPath.row
est nécessaire si la valeurdatasource.visibleRows
est 0.Il est plus facile de faire une démonstration dans le code:
la source