单元格中的破坏约束
Posted
技术标签:
【中文标题】单元格中的破坏约束【英文标题】:Broken constraints in the cell 【发布时间】:2018-05-19 16:30:32 【问题描述】:我需要在我的单元格中显示一些 UIView,但是这个 UIView (backView
) 的大小对于每个单元格是不同的。所以我也需要改变这个单元格的高度。
我正在尝试在运行时更改此backView
的高度和宽度,但我得到的只是一堆这样的自动布局错误:
[LayoutConstraints] 无法同时满足约束。将尝试通过打破约束来恢复...
我为这个单元格创建了 SimpleTextCell 类,它的 init 看起来像这样:
self.backView = UIView()
self.backView.translatesAutoresizingMaskIntoConstraints = false
self.backView.backgroundColor = UIColor.yellow
self.backView.layer.cornerRadius = 8.0
self.contentView.addSubview(backView)
let constraintBackViewTop = NSLayoutConstraint(item: backView, attribute: .top, relatedBy: .equal, toItem: contentView, attribute: .topMargin, multiplier: 1.0, constant: -5)
let constraintBackViewBottom = NSLayoutConstraint(item: backView, attribute: .bottom, relatedBy: .equal, toItem: contentView, attribute: .bottomMargin, multiplier: 1.0, constant: 5)
let constraintBackViewLeft = NSLayoutConstraint(item: backView, attribute: .left, relatedBy: .equal, toItem: contentView, attribute: .leftMargin, multiplier: 1.0, constant: 0)
constraintBackHeight = NSLayoutConstraint(item: backView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: superHeight)
constraintBackWidth = NSLayoutConstraint(item: backView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: superWidth)
self.contentView.addConstraints([constraintBackViewTop, constraintBackViewBottom, constraintBackViewLeft, constraintBackHeight, constraintBackWidth])
superHeight
和 superWidth
只是这里的一些默认值。
我的cellForRowAt
函数是这样的:
let cell = tableView.dequeueReusableCell(withIdentifier: "simpleTextCell", for: indexPath) as! SimpleTextCell
cell.selectionStyle = .none
cell.backgroundColor = UIColor.red
cell.constraintBackHeight.constant = 100
cell.constraintBackWidth.constant = 200
cell.updateConstraints()
而且它根本不起作用。我有错误(就像我之前提到的那样),虽然我的单元格的高度有点正确,但我的backView
是不可见的,因为backView.frame
的宽度为零(我不知道为什么) backView
的高度为 100(相同)。看来我的新约束被忽略了。
我尝试在cellForRowAt
中为这些约束设置优先级:
cell.constraintBackHeight.priority = UILayoutPriority.init(rawValue: 999)
结果是运行时错误。
我尝试通过以下方式克服此错误:
cell.constraintBackHeight.isActive = false
cell.constraintBackHeight.priority = UILayoutPriority.init(rawValue: 999)
cell.constraintBackHeight.isActive = true
但它也不起作用。
我该如何解决这个问题?
【问题讨论】:
为什么不制作一个自定义单元格来调整其内容的大小?您在数据源本身中设置和更新约束的方法是个坏主意。 这个 backView 实际上相当复杂,因为它包含几个 UILabel(我事先不知道它们的数量或大小,所以我无法在单元类中为它们创建约束)。所以我必须在 cellForRowAt 中计算容器的高度(backView)并更新容器的约束(高度和宽度)。我有一种感觉,这不是一个最佳解决方案,但现在它是我能想到的最好的解决方案。如果你有另一个,我会很高兴听到这个消息,谢谢。 首先,您不需要制作一个万能的单元格,尤其是当它在运行时被观察者和约束更改污染时。不要害怕制作多个满足不同配置的单元格,并在数据源中将正确的单元格出列。数据源应该尽可能精简,因为它被大量调用并且膨胀它会影响性能并消耗内存。如果必须,请考虑组合标签。但是,当您将单元格的子视图锚定到单元格的边缘时,单元格会自动调整大小。所以想出一个聪明的方法来使这项工作对你有利。 是的,我知道。我在此表中使用了几个自定义单元格,但我相信如果我为具有 2 个 UILabel、3 个 UILabel 等的单元格创建不同的类,那就太多了(不幸的是,我不想组合这些标签)。有问题的单元格是自定尺寸的,我遇到的问题是关于内部视图,它决定了单元格的高度,但可能比单元格窄。无论如何,谢谢,我会再考虑一下这个解决方案。 【参考方案1】:问题来了
constraintBackHeight = NSLayoutConstraint(item: backView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: superHeight)
constraintBackWidth = NSLayoutConstraint(item: backView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: superWidth)
您设置了 2 个高度限制,可能是您刚刚复制为宽度而忘记将其更改为 .width
【讨论】:
谢谢,你救了我。我仍然遇到自动布局错误,但它有效!以上是关于单元格中的破坏约束的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 UIImageView 和单元格中的多个标签正确地进行约束?