Changing Auto Layout constant doesn't update its frame
<p>I've created a little info view I'd like to add as a subview to a UIVisualEffectView. On my info view I created a free form xib and used Auto Layout for all the UILabels and one UIButton. The goal here is that <strong>Start, Pull</strong> and <strong>Sled</strong> are all optional so if that data doesn't exist I want to collapse those UILabels. I've accomplished this by updating their <strong>equal height</strong> constraint to 0. </p>

<p><strong>my  problem</strong> is when some or all of those optional UIlabels collapse I want to update the <code>UIView</code>'s frame's height so things are tidy and don't potentially have gaps.</p>

<p><a href="https://i.stack.imgur.com/M2sSN.png" rel="noreferrer"><img src="https://i.stack.imgur.com/M2sSN.png" alt="enter image description here"></a></p>

<p>I do the below to update the constraints I've tagged in IB.</p>

<pre><code>    for view in self.view.subviews {
        for constraint in view.constraints {
            if let identity = constraint.identifier {
                if labelTags.contains(identity) {
                    print("Before: \(view.frame)")
                    constraint.constant = labelHeight
                    view.setNeedsUpdateConstraints()
                    print("After: \(view.frame)")
                }
            }
        }
    }

Before: (5.0, 101.0, 50.0, 25.0)
After: (5.0, 101.0, 50.0, 25.0)
Before: (58.0, 101.0, 101.0, 25.0)
After: (58.0, 101.0, 101.0, 25.0)
Before: (5.0, 129.0, 39.0, 25.0)
After: (5.0, 129.0, 39.0, 25.0)
Before: (47.0, 129.0, 23.0, 25.0)
After: (47.0, 129.0, 23.0, 25.0)
Before: (5.0, 157.0, 45.0, 25.0)
After: (5.0, 157.0, 45.0, 25.0)
Before: (53.0, 157.0, 63.0, 25.0)
After: (53.0, 157.0, 63.0, 25.0)
</code></pre>

<p>After the constraints are updated I attempt to determine the view's frame by loops the views subview and get the max height like so:</p>

<pre><code>    var height:CGFloat = 0.0
    for v in self.view.subviews {
        if (v.frame.origin.y + v.frame.size.height) &gt; height {
            height = (v.frame.origin.y + v.frame.size.height)
        }
    }

    self.frame.size.height = height
</code></pre>

<p>On first load <strong>getting the new frame height doesn't work because the UILabels frames don't update after updating their constraints.</strong> Here is the kicker, the same code runs on orientation change and it works! When I rotate back to portrait all my <code>UILabels</code> are lined up nicely and the <code>UIView</code> is pulled up snuggly under the <code>UIButton</code>!</p>

<p>Any direction would be greatly appreciated, I've been at this for two days. Thanks!</p>

<p><strong>UPDATE:</strong> </p>

<p><code>self.view.layoutIfNeeded()</code> was indeed the winner! In my case timing was everything.</p>

<p>I have never have paid that close attention but the below appear to be more of a 'suggestion' to the OS where as <code>layoutIfNeeded()</code> is immediate.</p>

<pre><code>self.view.setNeedsUpdateConstraints()
self.view.setNeedsLayout()
self.view.setNeedsDisplay()
</code></pre>