Роздільні розділи: [Assert] Не вдається визначити новий глобальний індекс рядків для preReloadFirstVisibleRow (0)


9

Я реалізую заголовки розділів, що складаються в UITableViewController.

Ось як я визначаю, скільки рядків показувати за кожним розділом:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
    return self.sections[section].isCollapsed ? 0 : self.sections[section].items.count
}

Існує структура, яка містить інформацію про розділ із напилом для 'isCollapsed'.

Ось як я перемикаю їхні стани:

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()
}

Все прекрасно працює і оживляє, проте в консолі, коли згортається розширений розділ, я отримую це [Assert]:

[Assert] Не вдається визначити новий глобальний індекс рядків для preReloadFirstVisibleRow (0)

Це трапляється, незалежно від того, чи це той самий відкритий розділ, що закривається (згортається), чи я відкриваю інший розділ і "автоматично закриваю" раніше відкритий розділ.

Я нічого не роблю з даними; це стійко.

Хтось може допомогти пояснити, чого не вистачає? Дякую


Чи складається ваш перегляд таблиці з купою розділів і не так багато фактичних рядків?
Байрон Котзее

Вам коли-небудь вдалося це виправити?
PaulDoesDev

@ByronCoetsee Так, поки розділ не розгорнуто. Тож коли все згортається, це лише заголовки розділів. Коли один розгорнуто, це всі заголовки розділів для нерозширених розділів та заголовок розділу, а потім комірки для даних.
iOSProgrammingIsFun

@PaulDoesDev Я це зробив, але не за допомогою цього механізму. Я повністю переписав його так, що, хоча він виглядає однаково, він працює зовсім інакше. Однак я збираюся залишити це тут, якщо хтось може це витончено виправити, або це допомагає іншим чином.
iOSProgrammingIsFun

1
@iOSProgrammingIsFun ха-ха, так, я подумав, що це може здатися хаком, і це технічно, але кількість коду і той факт, що він насправді досить чистий, означає, що я можу дозволити собі спати вночі: P код розміщений нижче
Байрон Коетзе

Відповіді:


8

Для того щоб tableView знав, де він знаходиться під час перезавантаження рядків тощо, він намагається знайти "якірний рядок", який він використовує в якості посилання. Це називається а preReloadFirstVisibleRow. Оскільки цей tableView може не мати видимих ​​рядків у якийсь момент через всі секції згортаються, tableView заплутається, оскільки не може знайти якір. Потім він буде скинутий до вершини.

Рішення: Додайте 0 висотний рядок до кожної групи, що згортається. Таким чином, навіть якщо секція згортається, все ще присутній рядок (хоча висота 0px). Тоді tableView завжди має щось зачепити як орієнтир. Ви побачите це в дійсності, numberOfRowsInSectionдодавши рядок у, якщо кількість рядків дорівнює 0, і обробляти будь-які подальші indexPath.rowдзвінки, переконуючись, що потрібно повернути значення клітини phatom раніше indexPath.row, якщо datasource.visibleRowsце 0.

Простіше демонструвати код у коді:

func numberOfSections(in tableView: UITableView) -> Int {
    return datasource.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return datasource[section].visibleRows.count == 0 ? 1 : datasource[section].visibleRows.count
}

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    datasource[section].section = section
    return datasource[section]
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if datasource[indexPath.section].visibleRows.count == 0 { return 0 }
    return datasource[indexPath.section].visibleRows[indexPath.row].bounds.height
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if datasource[indexPath.section].visibleRows.count == 0 { return UITableViewCell() }

    // I've left this stuff here to show the real contents of a cell - note how
    // the phantom cell was returned before this point.

    let section = datasource[indexPath.section]
    let cell = TTSContentCell(withView: section.visibleRows[indexPath.row])
    cell.accessibilityLabel = "cell_\(indexPath.section)_\(indexPath.row)"
    cell.accessibilityIdentifier = "cell_\(indexPath.section)_\(indexPath.row)"
    cell.showsReorderControl = true
    return cell
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.