从 UITableView 中删除以编程方式自定义的 UITableViewCell 时约束中断

Posted

技术标签:

【中文标题】从 UITableView 中删除以编程方式自定义的 UITableViewCell 时约束中断【英文标题】:Constraints break when programmatically customized UITableViewCell is removed from UITableView 【发布时间】:2018-10-14 14:56:22 【问题描述】:

我正在使用UITableViewController,我正在加载自定义UITableViewCell。单元格中的所有元素和约束均以编程方式配置。 TableView 是这样的

除了删除单元格外,一切正常。我将 tableView 配置为在删除时淡化单元格。但是,该单元格有点晃动,然后它向左移动而不是淡出,并且我在控制台中收到自动布局错误消息:“无法同时满足约束”

"<NSLayoutConstraint:0x600002551a40 UIView:0x7fccbd5286f0.height == 100   (active)>",
"<NSLayoutConstraint:0x6000025505a0 V:|-(16)-[UIView:0x7fccbd5286f0]   (active, names: '|':UITableViewCellContentView:0x7fccbd541b10 )>",
"<NSLayoutConstraint:0x600002550730 UIView:0x7fccbd5286f0.bottom == UITableViewCellContentView:0x7fccbd541b10.bottom   (active)>",
"<NSLayoutConstraint:0x6000025605a0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fccbd541b10.height == 1.19209e-07   (active)>"

及以下

"<NSLayoutConstraint:0x6000025505a0 V:|-(16)-[UIView:0x7fccbd5286f0]   (active, names: '|':UITableViewCellContentView:0x7fccbd541b10 )>",
"<NSLayoutConstraint:0x600002550730 UIView:0x7fccbd5286f0.bottom == UITableViewCellContentView:0x7fccbd541b10.bottom   (active)>",
"<NSLayoutConstraint:0x6000025605a0 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7fccbd541b10.height == 1.19209e-07   (active)>"

下面的“将尝试通过打破约束来恢复”

<NSLayoutConstraint:0x600002551a40 UIView:0x7fccbd5286f0.height == 100   (active)>
<NSLayoutConstraint:0x600002550730 UIView:0x7fccbd5286f0.bottom == UITableViewCellContentView:0x7fccbd541b10.bottom   (active)>

我将控制台输出分成几部分,因为由于某种原因我无法将它们全部粘贴在一起。

基本上,我在单元格的contentView 内有一个名为cellView(白色圆角区域)的UIView。您看到的所有其他元素都在cellView 中。我在cellViewcontentView 之间应用了以下约束

cellView.translatesAutoresizingMaskIntoConstraints = false
cellView.heightAnchor.constraint(equalToConstant: 100).isActive = true
cellView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 16.0).isActive = true
cellView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
cellView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16.0).isActive = true
cellView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16.0).isActive = true

当我尝试在删除单元格之前停用单元格及其子视图中的所有约束时,它起作用了。但是,当新单元被重复使用时,它们没有激活限制。

我应该如何处理这种情况?

【问题讨论】:

【参考方案1】:

你需要降低底部约束的优先级

let con = cellView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)  
con.priority = UILayoutPriority(999)
con.isActive = true

【讨论】:

应用程序在启动时被终止 - Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Mutating a priority from required to not on an installed constraint (or vice-versa) is not supported. You passed priority 999 and the existing priority was 1000.' 你能不能把priority和isactive行交换一下试试 成功了,您的订单是正确的,我只是第一次没有按照您的订单。现在我在删除时在控制台中没有收到任何错误消息,但无论我在tableView.deleteRows(at: [indexPath!], with: .fade) 这很有趣……我投了赞成票,因为我遇到了类似的问题。你能解释发生了什么以及为什么会解决它吗?我很好奇。谢谢。 @dniswhite 当 tableView 加载优先级为 1000 时,表格的 contentView 有一个封装高度作为预设值,当有多个约束时肯定不会满足单元格从上到下的高度值与预设的高度值不同,这将导致冲突,因此使底部约束的优先级

以上是关于从 UITableView 中删除以编程方式自定义的 UITableViewCell 时约束中断的主要内容,如果未能解决你的问题,请参考以下文章

iOS:使用 IB 为以编程方式创建的 UITableView 创建自定义单元格

Swift UItableView 以编程方式自定义单元格(文档)?

从 UITableView 中删除自定义视图

如何在 Swift 中以编程方式从 UIView 中删除安全区域?

以编程方式从 MFC 工具栏中完全删除按钮

以编程方式将 UITableView 添加到侧边栏