Ios 以编程方式更改自动布局约束后,视图未更新

Ios 以编程方式更改自动布局约束后,视图未更新,ios,swift,autolayout,constraints,Ios,Swift,Autolayout,Constraints,在此之前,我必须说,我确实得到了我想要的可见效果,但不是以令人满意的方式,因为现在,约束需要“打破”,而不是适当地更新 我有一个ViewController,它有一个UITableView。该tableView的高度可以从0(不可见)到它所包含的任何行数不等。通过将当前行数乘以行的高度,在ViewController的viewDidLoad()中计算高度 我尝试的第一件事是创建一个@IBOutlet弱var tableHeightConstraint:NSLayoutConstraint连接到情

在此之前,我必须说,我确实得到了我想要的可见效果,但不是以令人满意的方式,因为现在,约束需要“打破”,而不是适当地更新

我有一个ViewController,它有一个UITableView。该
tableView
的高度可以从0(不可见)到它所包含的任何行数不等。通过将当前行数乘以行的高度,在ViewController的viewDidLoad()中计算高度

我尝试的第一件事是创建一个
@IBOutlet弱var tableHeightConstraint:NSLayoutConstraint连接到情节提要中设置的高度约束。它只有一些随机的初始高度,但在ViewController的
viewDidLoad()
中会更新到正确的值,然后使用方法在需要时更新视图:

tableHeightConstraint = NSLayoutConstraint(item: tableView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 0, constant: calculatedTableViewHeight)

// At this point I've tried a variety of methods like the following two but actually none has worked for me
view.layoutIfNeeded()

// or
view.updateConstraints()

// or
view.layoutSubviews()
。。。即使是tableView上的相同方法,也要确保将所有这些都放在
viewDidLayoutSubviews()

因此,我下一步尝试的是创建与上面相同的约束,但不是更新,而是将其添加到视图中:
view.addConstraint(tableHeightConstraint)
。这实际上达到了预期的视觉效果,但在日志中,我得到了这两个高度约束的冲突,导致了初始约束的中断。因为我的目标是得到一个正确和干净的代码,所以我一直在尝试。因此,这次我首先从视图中删除约束,然后再添加调整后的约束。在视觉上,一切都很完美,但我仍然没有摆脱相互冲突的约束


因此,我的实际问题是(除了我目前所做的错误之外),我如何——最好是——在任何时候更新一个现有的约束,然后对视图及其子视图进行适当的更新/重新显示,无论是在我第一次加载视图时,还是在用户交互时我只是想更改一些约束。非常感谢你的帮助

当前,您正在指定一个新约束,而不是更新当前约束。新约束也未添加到视图层次中

使用IBOutlet引用在IB中设置的约束是一种很好的方法,但您只需修改约束的常量,而不是为该变量指定新约束:

tableHeightConstraint.constant=calculatedTableHeight


您不需要在此处调用layoutifneedd(),因为当您更改其常量时,约束会自动处理对布局过程的调用<代码>更新约束()
布局子视图()
绝对不是您想要的

将属性设置为新约束不会删除旧约束,它只会使指针指向新约束,这就是为什么会出现冲突约束。你应该像@cmyr的答案那样做。@rdelmar好的,明白了,谢谢你的解释!但是,为什么在转到
视图时仍然存在冲突。removeConstraint(tableHeightConstraint)
,生成一个新的,并通过
视图将其再次添加到视图中。addConstraint(tableHeightConstraint)
?只是为了理解原因…那句话中的观点是什么?这是控制器的自我视图吗?在情节提要中创建的高度约束将添加到设置高度的视图中,即案例中的表视图(而不是superview)。您是否尝试过self.tableView.removeConstraint(tableHeightConstraint)?新的方法也应该添加到表视图中。对,我在ViewController的视图上执行了这些方法,而不是在嵌入式UITableView上!令人惊讶的是,虽然在self.view上删除似乎不成功,但self.view.addConstraint的工作方式是视觉效果正确的。事实上,这并不奇怪。您可以将高度约束添加到superview,但不应该添加(除非您正在以某种方式创建相对于superview大小的高度约束)。但当然,你不能从控制器的视图中删除它,因为它不在那里。我真的希望能够简单地更改指针以引用不同的约束,从而更优雅地在两种模式之间切换。但似乎任何更新消息都不会导致新引用的约束替换上一个约束。每次我想改变模式时,我都不得不添加和删除这些约束吗?@Michael:你对约束的引用是供你自己使用的;如果你在视图中添加了一个约束,但没有将对它的引用保存到任何地方,它仍然会被添加到视图中;当您将视图上的约束简单地看作一个项目数组时,更容易理解。链接到IBOutlet的XIB约束只是初始化约束并在第一次加载时将其添加到数组中的一种方法。更改控制器中的指针不会更改数组中已有的内容,而更改约束的属性(即常量)会更改值并产生实际效果。