Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a view controller laid out in a storyboard with autolayout enabled and am looking for a way to change constraints to allow for my view to rotate into landscape and rearrange buttons on the screen. When I try the code below, I get about two dozen "unable to satisfy constraints, breaking constraint..." messages that I cannot really decode.

Is there a way to dynamically replace constraints from a storyboard with constraints that I specify programmatically? I want to completely override the layout of the buttons that I defined in a storyboard.

-(void)updateViewConstraints
{
    [super updateViewConstraints];

    self.loginButton.translatesAutoresizingMaskIntoConstraints = NO;
    self.getStartedButton.translatesAutoresizingMaskIntoConstraints = NO;
    self.takeTourButton.translatesAutoresizingMaskIntoConstraints = NO;



    [self.loginButton removeConstraints:self.loginButton.constraints];
    [self.getStartedButton removeConstraints:self.getStartedButton.constraints];
    [self.takeTourButton removeConstraints:self.takeTourButton.constraints];


    one = self.loginButton;
    two = self.getStartedButton;
    three = self.takeTourButton;


    NSDictionary *metrics = @{@"height":@50.0,@"width":@100.0,@"leftSpacing":@110.0};
    NSDictionary *views = NSDictionaryOfVariableBindings(one,two,three);

    [self.view removeConstraints:activeTestLabelConstraints];
    [activeTestLabelConstraints removeAllObjects];

    if(isRotatingToLandscape)
    {

        [self registerConstraintsWithVisualFormat:@"|-[one(two)]-[two(three)]-[three]-|" options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:metrics views:views];
        [self registerConstraintsWithVisualFormat:@"V:[one(height)]-|" options:0 metrics:metrics views:views];

    }else
    {

        [self registerConstraintsWithVisualFormat:@"|-leftSpacing-[one(width)]" options:0 metrics:metrics views:views];
        [self registerConstraintsWithVisualFormat:@"[two(width)]" options:0 metrics:metrics views:views];
        [self registerConstraintsWithVisualFormat:@"[three(width)]" options:0 metrics:metrics views:views];
        [self registerConstraintsWithVisualFormat:@"V:[one(height)]-[two(75)]-[three(100)]-|" options:NSLayoutFormatAlignAllCenterX metrics:metrics views:views];
    }


}

Updated with Rob's answer, here's the method to remove constraints that I use

-(void)removeConstraintForView:(UIView*)viewToModify
{

    UIView* temp = viewToModify;
    [temp removeFromSuperview];
    [self.view addSubview:temp];

}
share|improve this question
add comment

1 Answer

up vote 3 down vote accepted

It sounds like you want to just remove all the constraints on a view. Since constraints on a view are often held by an ancestor of the view, it's not obvious how to remove all of the constraints easily. But it is actually pretty easy.

Removing a view from the view hierarchy removes any constraints betwixt the view and other views outside of it. So just remove your view from its superview and then add it back:

// Remove constraints betwixt someView and non-descendants of someView.
UIView *superview = someView.superview;
[someView removeFromSuperview];
[superview addSubview:someView];

If there are any constraints betwixt someView and its descendants, those constraints might be held by someView itself (but cannot be held by any descendants of someView). If you want to remove those constraints also, you can do so directly:

// Remove any remaining constraints betwixt someView and its descendants.
[someView removeConstraints:[someView constraints]];
share|improve this answer
    
Thanks, that worked ! –  Alex Stone Jul 26 '13 at 13:28
    
I noticed that removing the subview from superview does not seem to work for constraints defined for that subview (like pinned height and width ) –  Alex Stone Jul 29 '13 at 13:18
    
The second part of my answer will remove width and height constraints. –  rob mayoff Jul 29 '13 at 14:59
    
it worked.. but my problem is that if my uiview has buttons in its subviews, the buttons no longer receive touch events when i detach then re-attach their parent.. i donno how to work around that –  abbood Sep 26 '13 at 9:48
    
ok just so that nobody falls in the same trap as me.. i had to do several things to figure out what was the problem (although some are unrelated to the above problem.. i thought it still could help) 1. couldn't use the life saving recursiveDescription on my compiler log.. turned out my compiler optimization setting was turned on 2. figured out that by setting translatesAutoresizingMaskIntoConstraints = NO on the container view.. and not setting a width/height ..> –  abbood Sep 26 '13 at 11:48
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.