Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS: programmatically changing constraints set from Interface Builder

Good day, friends!

I failed trying to animate views that were set in IB from code. App crashes with following reason:

The view hierarchy is not prepared for the constraint...

I saw some similar questions here and the reason was always that the view which was created programmatically, is not yet added to superview. But I created all views in IB!

The console also says:

View not found in container hierarchy: (here goes it's superview)

It doesn't make any sense to me because in fact it is a subview of appropriate superview, and xcode knows it - it prints view hierarchy right away and it fits.

What could the reason? Thank you!

Edit: code I use:

    - (void)setEditingConstraintsForView:(UIView *)view
{
    // Pin given view to top, fix it height
    NSDictionary *givenView = @{@"view":view};
    view.translatesAutoresizingMaskIntoConstraints = NO;

    NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:givenView];
    NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view(height)]" options:0 metrics:@{@"height":@(viewHeight)} views:givenView];

    [self.animatedVIew addSubview:view];

    for (NSArray *constraints in @[horizontalConstraints, verticalConstraints]) {
        [view addConstraints:constraints];
    }
}

Also I delete all constraints that I set in IB before installing new:

    - (NSDictionary *)constraintsFromIB
{
    if (!_constraintsFromIB) {
        _constraintsFromIB = @{@"view1":self.view1.referencingConstraintsInSuperviews,
                               @"view2":self.view2.referencingConstraintsInSuperviews,
                               @"view3":self.view3.referencingConstraintsInSuperviews };
    }

    return _constraintsFromIB;
}

And then:

- (void)updateViewConstraints
{
    [super updateViewConstraints];

    // clear all constraints
    for (NSString *viewName in self.constraintsFromIB.allKeys) {
        for (NSLayoutConstraint *constraint in self.constraintsFromIB[viewName]) {
            [constraint remove];
           }

} }

UPDATE 2: Method I use invoke change: when user touches the view, this one is called:

- (void)animateConstraintsForState:(LDYEditingLabel)state
{
    self.editingLabel = state;        
    [UIView animateWithDuration:0.3 animations:^{
        [self updateViewConstraints];
        [self.view layoutIfNeeded];
    }];
}

Later in updateViewConstraints: there is a code that triggers my method setEditingConstraintsForView:(UIView *)view

like image 614
Aleksandr Shcherbakov Avatar asked Jan 16 '15 01:01

Aleksandr Shcherbakov


People also ask

How do I update constraints in programmatically in Swift?

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. Method updateConstraints() is an instance method of UIView . It is helpful when you are setting the constraints programmatically.


2 Answers

if you use IB to create constrains you can add constrains as outlet.

You then update the constrain and call [self updateViewConstraints]; in the animation block

enter image description here

like image 149
Charlie Wu Avatar answered Oct 25 '22 00:10

Charlie Wu


If it were me, I'd wire the constraints to IBOutlets and just modify the existing constraints. It would probably end up being easier than adding and removing them programmatically.

You may also need to call setNeedsLayout after you've modified the constraints.

like image 26
skwashua Avatar answered Oct 25 '22 00:10

skwashua