Implementuję zwijalne nagłówki sekcji w UITableViewController.
Oto jak określam, ile wierszy ma być wyświetlanych w poszczególnych sekcjach:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.sections[section].isCollapsed ? 0 : self.sections[section].items.count
}
Istnieje struktura, która przechowuje informacje o sekcji z wartością logiczną dla „isCollapsed”.
Oto jak przełączam ich stany:
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()
}
Wszystko działa i ładnie animuje, jednak w konsoli podczas zwijania rozwiniętej sekcji otrzymuję [Assert]:
[Assert] Nie można ustalić nowego globalnego indeksu wierszy dla preReloadFirstVisibleRow (0)
Dzieje się tak, niezależnie od tego, czy jest to ta sama otwarta sekcja, zamykanie (zwijanie), czy też otwieram inną sekcję i „automatycznie zamykam” poprzednio otwartą sekcję.
Nic nie robię z danymi; to jest trwałe.
Czy ktoś mógłby wyjaśnić, czego brakuje? Dzięki
ios
swift
assert
collapsable
uitableviewsectionheader
iOSProgrammingIsFun
źródło
źródło
Odpowiedzi:
Aby tableView wiedział, gdzie jest, podczas przeładowywania wierszy itp., Próbuje znaleźć „wiersz kontrolny”, który wykorzystuje jako odniesienie. To się nazywa
preReloadFirstVisibleRow
. Ponieważ tableView może nie mieć w dowolnym momencie żadnych widocznych wierszy ze względu na zwinięcie wszystkich sekcji, tableView może się mylić, ponieważ nie może znaleźć kotwicy. Następnie zresetuje się do góry.Rozwiązanie: Dodaj wiersz o wysokości 0 do każdej zwiniętej grupy. W ten sposób, nawet jeśli sekcja jest zwinięta, nadal jest obecny rząd (choć o wysokości 0px). TableView zawsze ma wtedy coś do zaczepienia jako odniesienie. Zobaczysz to po dodaniu wiersza,
numberOfRowsInSection
jeśli liczba wierszy wynosi 0, i obsłużeniu wszelkich dalszychindexPath.row
wywołań, upewniając się, że zwracana jest wartość komórki Phatom, zanimindexPath.row
będzie to konieczne, jeślidatasource.visibleRows
wynosi 0.Łatwiej jest demo w kodzie:
źródło