Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS7 issues with NSIBPrototypingLayoutConstraint autolayout constraints generated by Interface Builder

Previously in iOS6, my chat message view controller displayed and animated correctly with carefully constructed autolayout constraints in IB. Here's the current view hierarchy with the constraints removed in Xcode 5:

IB layout

After upgrading to XCode 5 and iOS7, I found I needed to clear all the old constraints in order to account for the default translucent status bar, otherwise my toolbar would fall under the status bar. This happened despite calling setEdgesForExtendedLayout: with UIRectEdgeNone.

I am now attempting to create all the constraints programmatically in viewDidLoad:

// self.view.translatesAutoresizingMaskIntoConstraints = NO; // errors either way
NSArray *viewHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_toolbar]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_toolbar)];
[self.view addConstraints:viewHorizConstraints];
viewHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_viewContainer]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_viewContainer)];
[self.view addConstraints:viewHorizConstraints];

NSArray *viewVertConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(20)-[_toolbar(44)]-[_viewContainer]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_toolbar, _viewContainer)];
[self.view addConstraints:viewVertConstraints];

NSArray *tableContainerVertConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_tableView(<=460@999)][_viewInputContainer(44)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_tableView, _viewInputContainer)];
[_viewTableContainer addConstraints:tableContainerVertConstraints];


NSArray *containerVertConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[_viewTableContainer][_viewOptions]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_viewTableContainer, _viewOptions)];
[_viewContainer addConstraints:containerVertConstraints];

//    _constraintContainerVertSpace = [NSLayoutConstraint constraintWithItem:_viewTableContainer attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:_viewContainer attribute:NSLayoutAttributeTrailing multiplier:1 constant:0]; // same as below

containerVertConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[_viewTableContainer]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_viewTableContainer)];
_constraintContainerVertSpace = [containerVertConstraints lastObject];
[_viewContainer addConstraint:_constraintContainerVertSpace];

containerVertConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=0)-[_viewOptions]-(>=-216@999)-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_viewOptions)];
[_viewContainer addConstraints:containerVertConstraints];

However, if I attempt to change the vertical space constraint between my containerView and tableContainerView, I get errors. (I'm trying to resize the tableContainerView to shrink with the appearance of the keyboard.)

[UIView animateWithDuration:0.25f
                      delay:0
                    options:UIViewAnimationOptionCurveEaseInOut
                 animations:^{
                     _constraintContainerVertSpace.constant = -keyboardHeight;
                 } completion:nil];

These are the constraints that fail to satisfy simultaneously:

(
"<NSIBPrototypingLayoutConstraint:0x140d7bb0 'IB auto generated at build time for view with fixed frame' V:|-(460)-[UIView:0x140ddef0]   (Names: '|':UIView:0x140dde60 )>",
"<NSIBPrototypingLayoutConstraint:0x140d7c10 'IB auto generated at build time for view with fixed frame' V:[UIView:0x140ddef0(44)]>",
"<NSLayoutConstraint:0x14d9db30 V:[UIView:0x140ddef0]-(0)-|   (Names: '|':UIView:0x140dde60 )>",
"<NSIBPrototypingLayoutConstraint:0x140e0290 'IB auto generated at build time for view with fixed frame' V:|-(0)-[UIView:0x140dde60]   (Names: '|':UIView:0x140dddd0 )>",
"<NSLayoutConstraint:0x14d9df60 V:[UIView:0x140dde60]-(-216)-|   (Names: '|':UIView:0x140dddd0 )>",
"<NSIBPrototypingLayoutConstraint:0x140e0830 'IB auto generated at build time for view with fixed frame' V:|-(64)-[UIView:0x140dddd0]   (Names: '|':UIView:0x140e0470 )>",
"<NSLayoutConstraint:0x14d9d820 V:[UIView:0x140dddd0]-(0)-|   (Names: '|':UIView:0x140e0470 )>",
"<NSAutoresizingMaskLayoutConstraint:0x1403a0b0 h=--& v=--& V:[UIView:0x140e0470(568)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x14d9db30 V:[UIView:0x140ddef0]-(0)-|   (Names: '|':UIView:0x140dde60 )>

UIView:0x140dde60 in this case is _viewTableContainer. 0x140ddef0 = _viewInputContainer. 0x140dddd0 = _viewContainer.

Why is this NSIBPrototypingLayoutConstraint V:|-(460)-[UIView:0x140ddef0(_viewInputContainer)] being created by IB when I've set translatesAutoresizingMaskIntoConstraints to NO, and when I've already defined unambiguous vertical constraints between _viewInputContainer and the _tableView above it?

I've tried using Cocoa Layout in Instruments, but there's too much noise to make any sense of it.

like image 278
oohaba Avatar asked Sep 24 '13 07:09

oohaba


3 Answers

I had to manually remove constraints on the views in addition to using translatesAutoresizingMaskIntoConstraints.

[_viewContainer removeConstraints:_viewContainer.constraints];
[self.view removeConstraints:self.view.constraints];

After adding these changes, there were no more errors with animating.

like image 69
oohaba Avatar answered Oct 21 '22 15:10

oohaba


In order to remove the NSIBPrototypingLayoutConstraint generated by IB, it can be solved by adding some dummy constraints on the IB, and set them remove at build time. Then, IB won't generate the NSIBPrototypingLayoutConstraint for you.

like image 37
AechoLiu Avatar answered Oct 21 '22 15:10

AechoLiu


Obligatory Swift:

view.removeConstraints(view.constraints)

Alternatively, if you want to remove constraints for one particular interface item in code, you can remove them for just one object. Here are a few examples:

myTableView.removeConstraints(myTableView.constraints)
myButton.removeConstraints(myButton.constraints)
myImageView.removeConstraints(myImageView.constraints)

This can be particularly useful if you are, for example, creating a paid or free version of an app. You can do most of the interface layout in interface builder and then make tweaks to the layout in code using Visual Format Language.

like image 29
Adrian Avatar answered Oct 21 '22 13:10

Adrian