Search code examples
iosswiftautolayoutnslayoutconstraint

How to force a constraint to update in the Auto Layout


I use AutoLayout to place my subviews within the superview. What I want from AutoLayout engine - is to calculate the width for the subview of UIView type and then in the same pass use this value for updating the position of this subview within its superview to make proper distribution of my subviews. I use NSLayoutConstraints type constraints for setting AutoLayout. My subview's width is equal to my view's height:

timer.heightAnchor.constraint(equalTo: (timer.widthAnchor)!, multiplier: 1).isActive = true

When I apply the set of constraints for a subviews, AutoLayout calculates theirs width and height based on padding for top and bottom constants. That all stuff worked fine.When I tried to use subview's width for constraint's constants, that I expected to be calculated in one pass:

timer.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: (self.view.bounds.width - 2*timer.bounds.width)/3)

I have got no luck here. I try to understand what is wrong and ended up with conclusion that on the moment when I apply my constraints and activate them the AutoLayout hasn't got updated value of subview's width. That become obvious when I try to:

print("timer.bounds.width", timer.bounds.width)

and got 0.0. I found similar questions here on the Stack and try to use

self.view.setNeedsLayout()
self.view.layoutIfNeeded()
print("now timer's width is =", timer!.bounds.width)

Yes, now I got the timer width in the same pass, not "0", but the AutoLayout still doesn't use it. The question is - how to force AutoLayout to use the updated value in the constraint constant.


Solution

  • The working solution appeared to be simple - in the same pass just update constant value of my constraint that uses that width:

      MyTimer.constant = timer!.bounds.width 
    

    and than use AutoLayout engine to calculate the position of subview using updated constraint calling self.view.layoutIfNeeded() again. It's not a great solution from a point of resources consumption. But for this particular case of my layout with uniform spacing it's pretty good one. What was not obvious that despite having reference on the variable in constant for the constraint I have to do it again.