Ios UITableView自调整单元格大小/节头重新加载UI错误

Ios UITableView自调整单元格大小/节头重新加载UI错误,ios,swift,xcode,uitableview,Ios,Swift,Xcode,Uitableview,很多时候,当我重新加载数据,重新加载某些特定的节/行时,我都会遇到单元格/节标题“闪烁的问题。如果只显示项目,则所有内容都具有正确的框架。但是当我需要重新加载它们时,错误就会出现 当我用硬编码的值表示单元格的高度或截面的高度时,这个错误就消失了 这是密码 self.tableView.rowHeight = UITableViewAutomaticDimension self.tableView.sectionHeaderHeight = UITableViewAutomaticDimensio

很多时候,当我重新加载数据,重新加载某些特定的节/行时,我都会遇到单元格/节标题“闪烁的问题。如果只显示项目,则所有内容都具有正确的框架。但是当我需要重新加载它们时,错误就会出现

当我用硬编码的值表示单元格的高度或截面的高度时,这个错误就消失了

这是密码

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 40
self.tableView.estimatedSectionHeaderHeight = 40
节和行本身都有正确的约束。然后,当我需要更新单元格时,我尝试调用
reloadCell
reloadSection
reloadData
。每个方法都会产生一个闪烁的问题。这是gif-

有两个问题

注意:每次单击单元格时,我都调用
reloadData()
。几乎可以肯定这没什么大不了的,因为它与任何更新内容的方式都不兼容

1。当你向下滚动并单击某个单元格时,它会向上滚动一点。我还发现它滚动到的位置取决于
estimatedHeight
值。有人能解释一下UITableView是如何使用这些值的吗?确切地说,它根据估计值设置contentSize,以及何时以及如何将自身重新加载到最终内容大小

2.我添加了
beginUpdate()
endUpdates()
来向您显示每次调用
reloadData()
时发生的节头闪烁的错误

这些是已知的iOS bug吗?因为他们看起来真的很好。我有正确的约束,我不做任何自定义操作。当我设置硬编码值并以通常的
heightFor…
方法返回它们时,一切看起来都很好。但由于自调整单元格大小是本机功能,我希望最终至少使用一次,而不会出现任何UI问题:)

更新: 对代码的一些补充:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let (section, preference) = self.sectionPreferenceFor(indexPath: indexPath)

    if section.type == .Multiple {
        preference.selected = !preference.selected
    } else {
        (section.items!.array as! [Preference])!.forEach({ $0.selected = false })
        preference.selected = true
    }
    tableView.reloadData()
}
为了显示bug#2,我刚刚将
tableView.reloadData()
包装为
beginUpdates()
endUpdates()

以下是我在
viewDidLoad()中看到的内容:

而且,通常在行/节的配置中没有什么特殊之处

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    if section == 0 {
        let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: String.init(describing: PreferenceMessageSectionHeaderView.self)) as?PreferenceMessageSectionHeaderView
        view?.configureWith(message: self.headerMessage)
        return view
    } else {
        let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: String.init(describing: PreferenceSectionHeaderView.self)) as? PreferenceSectionHeaderView
        view?.configureWith(title: section.name)
        return view
    }
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let (section, preference) = self.sectionPreferenceFor(indexPath: indexPath)

    if section.type == .Single {
        let cell = tableView.dequeueReusableCell(withIdentifier: String.init(describing: RadioButtonCell.self)) as! RadioButtonCell
        cell.configureWith(title: preference.name, selected: preference.selected)
        return cell
    } else {
        let cell = tableView.dequeueReusableCell(withIdentifier: String.init(describing: CheckBoxCell.self)) as! CheckBoxCell
        cell.configureWith(title: preference.name, selected: preference.selected)
        return cell
    }
}

你能展示你剩下的代码吗?@aaqibhussan当然。我更新了帖子。你是不是直接访问自定义单元格对象而不是重新加载tableView来尝试的?@AaqibHussain,我知道这会解决问题。有很多变通方法,但我正在努力最终找到一个本地解决方案。我不知道,也许我的自动调整电池出了问题。这就是为什么我决定在这里问…@StasIvanov-我以前见过类似的事情,但从未看到解决方案。我认为这要么是一个“bug”要么是“对不起,不能很好地处理多个节头”。你能展示你的其余代码吗?@aaqibhussan当然。我更新了帖子。你是不是直接访问自定义单元格对象而不是重新加载tableView来尝试的?@AaqibHussain,我知道这会解决问题。有很多变通方法,但我正在努力最终找到一个本地解决方案。我不知道,也许我的自动调整电池出了问题。这就是为什么我决定在这里问…@StasIvanov-我以前见过类似的事情,但从未看到解决方案。我认为这要么是一个“bug”,要么是“对不起,不能很好地处理多个节头”。
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    if section == 0 {
        let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: String.init(describing: PreferenceMessageSectionHeaderView.self)) as?PreferenceMessageSectionHeaderView
        view?.configureWith(message: self.headerMessage)
        return view
    } else {
        let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: String.init(describing: PreferenceSectionHeaderView.self)) as? PreferenceSectionHeaderView
        view?.configureWith(title: section.name)
        return view
    }
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let (section, preference) = self.sectionPreferenceFor(indexPath: indexPath)

    if section.type == .Single {
        let cell = tableView.dequeueReusableCell(withIdentifier: String.init(describing: RadioButtonCell.self)) as! RadioButtonCell
        cell.configureWith(title: preference.name, selected: preference.selected)
        return cell
    } else {
        let cell = tableView.dequeueReusableCell(withIdentifier: String.init(describing: CheckBoxCell.self)) as! CheckBoxCell
        cell.configureWith(title: preference.name, selected: preference.selected)
        return cell
    }
}