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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26512628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:17:46  来源:igfitidea点击:

View is not updating after changing auto-layout constraints programmatically

iosswiftautolayoutconstraints

提问by Alexei S.

Beforehand I have to say that I actually got the visible effect I've wanted but not in a satisfying way since, right now, constraints need to be "broken" instead of being properly updated.

事先我不得不说我实际上得到了我想要的可见效果,但不是以令人满意的方式,因为现在需要“打破”约束而不是正确更新。

I got a ViewController which holds a UITableView. The height of that tableViewcan vary from 0 (not visible) to whatever the number of rows it holds is. The height is calculated in the ViewController's viewDidLoad() by multiplying the current number of rows by the row's height.

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

The first thing I've tried was creating an @IBOutlet weak var tableHeightConstraint: NSLayoutConstraint!connected to the height constraint set in the storyboard. It has just some random initial height but it is updated to the correct value within the ViewController's viewDidLoad()followed by method that updates the view if needed:

我尝试的第一件事是创建一个@IBOutlet weak 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()

... and even the same methods on tableView just to be sure as well as putting all these in viewDidLayoutSubviews()instead.

...甚至 tableView 上的相同方法只是为了确保以及将所有这些都放入viewDidLayoutSubviews()

So what I tried next was to create the same constraint as above but instead of updating I just added it to the view: view.addConstraint(tableHeightConstraint). This actually had the desired visual effect but in the logs I got a conflict of these two height constraints resulting in a break of the initial one. As my goal is to get a correct and clean code I've kept trying. So this time I first removed the constraint from the view before adding the adjusted one again. Visually, again, everything was perfect but I still didn't get rid of the conflicting constraints.

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

So my actual question is (besides what I was doing wrong so far) how I can - preferably - just update an existing constraint followed by a proper update/relayout of the view and its subviews at any point, whether it is when I first load a view or whether I just want to change some constraints when the user interacts. Thanks a lot for any help!

所以我的实际问题是(除了到目前为止我做错了什么)我如何 - 最好 - 只需更新现有约束,然后在任何时候对视图及其子视图进行适当的更新/重新布局,无论是在我第一次加载时一个视图或者我是否只想在用户交互时更改一些约束。非常感谢您的帮助!

回答by cmyr

Currently, you're assigning a new constraint, instead of updating the current one. The new constraint also hasn't been added to the view hierarchy.

目前,您正在分配一个新的约束,而不是更新当前的约束。新约束也没有添加到视图层次结构中。

Your approach of using an IBOutlet to reference a constraint you set up in IB is a good approach, but instead of assigning a new constraint to that var, you just need to modify the constraint's constant:

您使用 IBOutlet 来引用您在 IB 中设置的约束的方法是一种很好的方法,但不是为该 var 分配新约束,您只需要修改约束的常量:

tableHeightConstraint.constant = calculatedTableHeight.

tableHeightConstraint.constant = calculatedTableHeight.

You shouldn't need to call layoutIfNeeded() here, since constraints handle calling a layout pass automatically when you change their constants. updateConstraints()and layoutSubviews()are definitely not what you want.

您不需要在此处调用 layoutIfNeeded(),因为当您更改其常量时,约束会自动处理调用布局传递。updateConstraints()并且layoutSubviews()绝对不是你想要的。