0
votes

I have a UILabel outlet that has its top space to superview and leading space to superview set to 20 in storyboard. I want to press a button to dynamically change the constraints to be centered vertically and horizontally. The vertical dynamic change is working fine, but the horizontal dynamic change isn't changing anything:

@IBAction func moveLabel(sender: AnyObject) {
    self.view.addConstraint(NSLayoutConstraint(
        item: self.label,
        attribute: NSLayoutAttribute.CenterY,
        relatedBy: NSLayoutRelation.Equal,
        toItem: self.view,
        attribute: NSLayoutAttribute.CenterY,
        multiplier: 1,
        constant: 0))

    self.view.addConstraint(NSLayoutConstraint(
        item: self.label,
        attribute: NSLayoutAttribute.CenterX,
        relatedBy: NSLayoutRelation.Equal,
        toItem: self.view,
        attribute: NSLayoutAttribute.CenterX,
        multiplier: 1,
        constant: 0))
}

The horizontal spacing stays at 20 leading from superview, but the vertical spacing is correctly applied to be centered. Why isn't the horizontal center working?

1
Do you get any warnings in the console? Are you deleting the constraints you made in the storyboard before you add these new ones? If not, I'm surprised either of them would work.rdelmar
Did you set: view.setTranslatesAutoresizingMaskIntoConstraints(false)Samaga
@Samaga, that is unnecessary. The label was made in the storyboard, so translatesAutoresizingMaskIntoConstraints is already false.rdelmar
I agree with rdelmar, Take an outlet to the leading space constraint and vertical space and remove them before calling move label. u can use "removeConstraint()" method to accomplish this.Suhas Aithal

1 Answers

1
votes

If you already have a top constraint in the storyboard, you need to deactivate that one for the new constraints to apply and not to have a crash.

You should not add constraints every time you want to move the label. You should add the constraints only one time, in viewDidLoad or even the storyboard, create IBOutlets for them and activate/deactivate them accordingly.

So your code would look something like this:

@IBOutlet weak var topOffsetConstraint : NSLayoutConstraint 
@IBOutlet weak var leadingOffsetConstraint : NSLayoutConstraint
@IBOutlet weak var horizontalCenterConstraint : NSLayoutConstraint
@IBOutlet weak var verticalOffsetConstraint : NSLayoutConstraint

@IBAction func moveLabel(sender: AnyObject) {
     topOffsetConstranint.active = NO;
     leadingOffsetConstraint.active = NO;
     horizontalCenterConstraint.active = YES;
     verticalOffsetConstraint.active = YES;

     // If you don't need to animate the changes, remove the animation block
     UIView.animateWithDuration(0.3) {
           self.view.layoutIfNeeded();
     }
}

I assumed that you would want to move the label back and forth. If this is not the case and your moveLabel method is called only once, your code should work. Just make sure to deactivate the constraints set in the storyboard and call layoutIfNeeded (maybe in an animation block, if this is what you need).

Hope this helps with your problem! Let me know how it goes