Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View is not updating after changing auto-layout constraints programmatically

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 tableView can 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.

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:

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.

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.

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!

like image 222
Alexei S. Avatar asked Oct 22 '14 16:10

Alexei S.


Video Answer


1 Answers

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:

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.

like image 192
cmyr Avatar answered Sep 19 '22 22:09

cmyr