139

I have a UIView and I set the constraints using Xcode Interface Builder.

Now I need to update that UIView instance's height constant programmatically.

There is a function that goes like myUIView.updateConstraints(), but I don't know how to use it.

shim
  • 9,289
  • 12
  • 69
  • 108
Chris Mikkelsen
  • 3,987
  • 9
  • 29
  • 41
  • Take outlet of the height constraint and set programetically – Muzahid Mar 08 '17 at 11:16
  • you can use [this link](http://stackoverflow.com/questions/30171366/why-cant-i-change-the-views-frame-size-in-swift) or [this link](http://stackoverflow.com/questions/26706565/how-do-i-change-uiview-size) for references. – Amna Farhan Mar 08 '17 at 11:16
  • Here is a way to update single or multiple constraints. https://stackoverflow.com/a/54171693/8861442 – Sarath Kumar Rajendran Jan 13 '19 at 18:10

10 Answers10

286

Select the height constraint from the Interface builder and take an outlet of it. So, when you want to change the height of the view you can use the below code.

yourHeightConstraintOutlet.constant = someValue
yourView.layoutIfNeeded()

Method updateConstraints() is an instance method of UIView. It is helpful when you are setting the constraints programmatically. It updates constraints for the view. For more detail click here.

Parth Adroja
  • 13,198
  • 5
  • 37
  • 71
  • 80
    Today I learned that Constraints can be turned into an outlet, and from there I can do whatever I wish to do with it. Thanks – Chris Mikkelsen Mar 08 '17 at 11:41
  • @ParthAdroja, bro could you please take a look at my question https://stackoverflow.com/questions/46034278/how-to-adjust-uiview-height-according-to-the-collection-view-content-height-in-s ? – May Phyu Sep 04 '17 at 10:35
  • I don't have a xib file, and how to set yourHeightConstraint in a UIView programmatically? – newszer Mar 14 '18 at 02:49
  • @newszer you need to look to other topic for that https://stackoverflow.com/questions/31651022/how-to-create-layout-constraints-programmatically – Parth Adroja Mar 14 '18 at 07:07
  • i heard that we should call layoutIfNeeded after change constant constraint. why? and sometimes i call layoutIfNeeded inside viewWillLayoutSubviews and viewDidLayoutSubviews. is it okay? – axunic Mar 14 '18 at 07:57
  • I did not know that we could create an outlet on a constraint. This is realy usefull. Thanks – Regis St-Gelais Mar 21 '18 at 12:15
  • @ParthAdroja But how to update the constraint based on the device... Can we switch the constraint value using UIDevice and device identifier...?? – Venkatesh Chejarla Dec 24 '18 at 05:48
  • @VenkateshChejarla You can check size classes docs for different devices or you can use UIDevice condition programatically and apply constraints accordingly. – Parth Adroja Dec 24 '18 at 05:50
  • @ParthAdroja As we are talking for the constraint to be updated programmatically, it would be much perfect if you can update the answer with the basic idea of how change constraint value based device using device identifier.. Just saying.. But best answer though.. Thanks.... – Venkatesh Chejarla Dec 24 '18 at 05:55
  • Thank you so much for helpful answer. @Parth Adroja. – Bhavsang Jam Apr 01 '19 at 12:28
  • IS the call to layoutIfNeeded needed at all?\ – Shivam Pokhriyal Sep 20 '19 at 07:38
  • how can this logic be applied to non IB views? How can I create an instance of a constraint constant? –  Jun 25 '20 at 01:21
123

If you have a view with multiple constrains, a much easier way without having to create multiple outlets would be:

In interface builder, give each constraint you wish to modify an identifier:

enter image description here

Then in code you can modify multiple constraints like so:

for constraint in self.view.constraints {
    if constraint.identifier == "myConstraint" {
       constraint.constant = 50
    }
}
myView.layoutIfNeeded()

You can give multiple constrains the same identifier thus allowing you to group together constrains and modify all at once.

George Filippakos
  • 16,359
  • 15
  • 81
  • 92
  • This works well but I am finding it easier to use just a regular outlet collection to group the constraints. For example, on the view that I am working with there are 47 constraints but only 6 that I want to change at runtime so it's a much smaller loop. This also doesn't require keeping strings in sync between two different places. – Gary Z Jan 21 '18 at 07:04
  • Hi, I am using it the same way, but it never goes in the if case and I have given the same identifier. – Rob13 Dec 18 '18 at 11:21
  • 1
    I was wondering if it was possible to name constraint. Great answer! – ShadeToD Feb 18 '19 at 15:24
  • If the item you want to constraint is inside a subview, use an outer for loop: `for subview in view.subviews` – Muhammed Gül May 20 '20 at 14:13
64

Change HeightConstraint and WidthConstraint Without creating IBOutlet.

Note: Assign height or width constraint in Storyboard or XIB file. after fetching this Constraint using this extension.

You can use this extension to fetch a height and width Constraint:

extension UIView {

var heightConstraint: NSLayoutConstraint? {
    get {
        return constraints.first(where: {
            $0.firstAttribute == .height && $0.relation == .equal
        })
    }
    set { setNeedsLayout() }
}

var widthConstraint: NSLayoutConstraint? {
    get {
        return constraints.first(where: {
            $0.firstAttribute == .width && $0.relation == .equal
        })
    }
    set { setNeedsLayout() }
}

}

You can use:

yourView.heightConstraint?.constant = newValue 
Paul
  • 115
  • 2
  • 10
AshvinGudaliya
  • 3,234
  • 19
  • 37
18

Drag the constraint into your VC as an IBOutlet. Then you can change its associated value (and other properties; check the documentation):

@IBOutlet myConstraint : NSLayoutConstraint!
@IBOutlet myView : UIView!

func updateConstraints() {
    // You should handle UI updates on the main queue, whenever possible
    DispatchQueue.main.async {
        self.myConstraint.constant = 10
        self.myView.layoutIfNeeded()
    }
}
aphoe
  • 2,586
  • 1
  • 27
  • 31
dylanthelion
  • 1,760
  • 15
  • 23
12

You can update your constraint with a smooth animation if you want, see the chunk of code below:

heightOrWidthConstraint.constant = 100
UIView.animate(withDuration: animateTime, animations:{
self.view.layoutIfNeeded()
})
  • I'm wondering why does my constant change show immediately even without calling an animation or layoutIfNeeded? iOS 15 – Programmer Feb 05 '22 at 15:32
7

To update a layout constraint you only need to update the constant property and call layoutIfNeeded after.

myConstraint.constant = newValue
myView.layoutIfNeeded()
Fran Martin
  • 2,369
  • 22
  • 19
6

First connect the Height constraint in to our viewcontroller for creating IBOutlet like the below code shown

@IBOutlet weak var select_dateHeight: NSLayoutConstraint!

then put the below code in view did load or inside any actions

self.select_dateHeight.constant = 0 // we can change the height value

if it is inside a button click

@IBAction func Feedback_button(_ sender: Any) {
 self.select_dateHeight.constant = 0

}
Nimisha joshy
  • 326
  • 4
  • 6
5

If the above method does not work then make sure you update it in Dispatch.main.async{} block. You do not need to call layoutIfNeeded() method then.

Nupur Sharma
  • 1,106
  • 13
  • 15
  • This worked when my code in `viewWillAppear()` wasn't changing the constraints. But the better solution I found was to move the code into `viewDidLayoutSubviews()`. – Gavin Wright Nov 05 '22 at 03:35
2
Create an IBOutlet of NSLayoutConstraint of yourView and update the constant value accordingly the condition specifies.

//Connect them from Interface 
@IBOutlet viewHeight: NSLayoutConstraint! 
@IBOutlet view: UIView!

private func updateViewHeight(height:Int){
   guard let aView = view, aViewHeight = viewHeight else{
      return
   }
   aViewHeight.constant = height
   aView.layoutIfNeeded()
}
CrazyPro007
  • 1,006
  • 9
  • 15
0

If you update your constraints with animation then add layout subview in UIView.animate...
for example,

@IBOutlet viewHeight: NSLayoutConstraint! 
@IBOutlet view: UIView!

private func updateViewHeight(height:Int){
   guard let aView = view, aViewHeight = viewHeight else{
      return
   }
 aViewHeight.constant = height
 UIView.animateWithDuration(0.5, delay: 0) { [self] in
   aView.layoutIfNeeded()
 }
}