可折叠部分:[断言] 无法确定预 ReloadFirstVisibleRow (0) 的新全局行索引
Collapsable Sections: [Assert] Unable to determine new global row index for preReloadFirstVisibleRow (0)
我正在 UITableViewController 中实现可折叠部分 headers。
以下是我确定每个部分显示多少行的方法:
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] Unable to determine new global row index for preReloadFirstVisibleRow (0)
这种情况会发生,无论它是同一个打开的部分、关闭(折叠),还是我打开另一个部分和 'auto-closing' 之前打开的部分。
我没有对数据做任何事情;那是执着的。
任何人都可以帮助解释缺少的内容吗?谢谢
为了让 tableView 在重新加载行等时知道它在哪里,它会尝试找到它用作参考的 "anchor row"。这称为 preReloadFirstVisibleRow
。由于此 tableView 可能由于所有部分都被折叠而在某些时候没有任何可见行,因此 tableView 会因为找不到锚点而感到困惑。然后它将重置到顶部。
解法:
向折叠的每个组添加一个高度为 0 的行。这样,即使折叠了一个部分,仍然存在一行(尽管高度为 0 像素)。然后 tableView 总是有一些东西可以挂钩作为参考。如果行数为 0,您将通过在 numberOfRowsInSection
中添加一行并通过确保 return 在 [=13] 之前处理任何进一步的 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
}
我正在 UITableViewController 中实现可折叠部分 headers。
以下是我确定每个部分显示多少行的方法:
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] Unable to determine new global row index for preReloadFirstVisibleRow (0)
这种情况会发生,无论它是同一个打开的部分、关闭(折叠),还是我打开另一个部分和 'auto-closing' 之前打开的部分。
我没有对数据做任何事情;那是执着的。
任何人都可以帮助解释缺少的内容吗?谢谢
为了让 tableView 在重新加载行等时知道它在哪里,它会尝试找到它用作参考的 "anchor row"。这称为 preReloadFirstVisibleRow
。由于此 tableView 可能由于所有部分都被折叠而在某些时候没有任何可见行,因此 tableView 会因为找不到锚点而感到困惑。然后它将重置到顶部。
解法:
向折叠的每个组添加一个高度为 0 的行。这样,即使折叠了一个部分,仍然存在一行(尽管高度为 0 像素)。然后 tableView 总是有一些东西可以挂钩作为参考。如果行数为 0,您将通过在 numberOfRowsInSection
中添加一行并通过确保 return 在 [=13] 之前处理任何进一步的 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
}