可折叠节:[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]:

[声明]无法为preReloadFirstVisibleRow(0)确定新的全局行索引

无论是同一个打开的节,关闭(合拢),还是我要打开另一个节并“自动关闭”先前打开的节,都会发生这种情况。

我对数据不做任何事情;这是持久的。

谁能帮助解释所缺少的内容吗?谢谢


您的表视图是否由一堆部分组成,却没有多少实际行?
拜伦·库切

您曾经设法解决此问题吗?
PaulDoesDev

@ByronCoetsee是的,直到扩展了一个部分。因此,当所有折叠都只是部分标题时。当一个被展开时,它是未展开部分的所有部分标题,然后是部分标题,然后是数据单元。
iOSProgrammingIsFun

@PaulDoesDev我做了,但是没有使用这种机制。我完全重写了它,以便它看起来一样,但工作原理完全不同。但是,如果有人可以优雅地解决此问题,或者以某种方式对他人有所帮助,我将在此保留。
iOSProgrammingIsFun

1
@iOSProgrammingIsFun哈哈是的,我认为它看上去好像是一个黑客,它在技术上是,但我的代码可以让量和事实,即它实际上是非常干净的手段自己在晚上睡觉时:P码贴在下面
拜伦Coetsee

Answers:


8

为了让tableView在重新加载行等时知道它在哪里,它试图找到一个“锚行”以用作参考。这称为preReloadFirstVisibleRow。由于此表视图由于所有部分都已折叠而在某一时刻可能没有任何可见的行,因此表视图会因为找不到锚点而感到困惑。然后它将重置到顶部。

解决方案: 向每个折叠的组添加一个高度为0的行。这样,即使一个部分被折叠,仍然存在一行(尽管高度为0px)。然后,tableView总是有一些东西可以作为参考。numberOfRowsInSection如果rowcount为0,则在行中添加一行,然后indexPath.row通过确保返回0(indexPath.row如果需要则返回之前需要的相单元格值)来处理任何进一步的调用,您将看到此效果datasource.visibleRows

使用代码进行演示更容易:

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
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.