how to set adaptive layout at run time? - ios

how to set adaptive layout at run time?
I am developing iOS app using adaptive layout with multiple views. I want to change the views position when keyboard will pop up.
I am using below auto layout coding it was not working.
NSArray *constraint_POS_V = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-vSpacing-[redView]-vSpacing-|" options:NSLayoutFormatDirectionLeadingToTrailing
metrics:metrics
views:viewsDictionary];
NSArray *constraint_POS_H = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-hSpacing-[redView]-hSpacing-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:metrics
views:viewsDictionary];
[self.view addConstraints:constraint_POS_V];
[self.view addConstraints:constraint_POS_H];

You have to set the constant value for the constraint at runtime. Take outlet for top layout constraint (viewTopLayoutConstraint) for the view.
- (void) keyboardWillShow:(NSNotification *) notification
{
[UIView animateWithDuration:0.3 animations:^
{
_viewTopLayoutConstraint.constant = -100;
[self.view layoutIfNeeded];
}];
}

Related

Changing programmatic/VFL constraints on-the-fly

I'm manually adding a subview to a view and am positioning it with constraints...
UIView *superview = self.view;
UIView *subview = self.subview;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(superview, subview);
[self.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(0)-[subview]-(0)-|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:viewsDictionary]];
[self.superview addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(0)-[subview]-(0)-|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:viewsDictionary]];
This positions my subview neatly in the superview. However, at a later time I would like to apply a margin around my subview (with animation) so that it is inset by 100. So in effect, my constraints in visual format language would be...
"H:|-(100)-[subview]-(100)-|"
"V:|-(100)-[subview]-(100)-|"
How can I attach variables to my 'margin' value so that I can transition between the two types of display for the subview?
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(0)-[subview]-(0)-|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:viewsDictionary]
Will return an array with the constraints in the same order that they were specified, you can look for it inside the array and then change its constant value.
But I think the easiest way is to create a reference to it like so (you can store it in an internal variable or property):
NSLayoutConstraint* space = [NSLayoutConstraint constraintWithItem:self.button1 attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual toItem:self.button2
attribute:NSLayoutAttributeLeft multiplier:1.0 constant:12.0];
and add it like this:
[self.view addConstraints:#[space]];
then you can change space.constant to some value. and animate it like so:
[UIView animateWithDuration:1.0 animations:^{
// Make all constraint changes here
[self.view layoutIfNeeded];}];
Other approach would be to remove all constraints and add VFL constraints with updated values, and then perform layoutIfNeeded inside the animation block as above.

UIView programatic constraint height increase when keyboard present

I'm building a comment input control for an app. This control consists of a UITextView embedded in a UIView. All constraints are being handled programatically. What happens is when the user taps the UITextView, the keyboard will open. This calls the keyboard observer methods and I then adjust the bottom constraint for the comment input control to move up with the keyboard. However, I am also trying to increase the height of the input control at the same time so the user has more room to type. I'm having trouble achieving this.
-(void)updateViewConstraints
{
NSDictionary *views = #{
#"table" : self.commentsTableView,
#"seeMoreComments" : self.seeMoreCommentsView,
#"commentInput" : self.commentEntryInput
};
//See More Comments Constraints
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[seeMoreComments]-0-|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[seeMoreComments(45)]" options:0 metrics:nil views:views]];
//Table view constraints
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[table]-0-|" options:0 metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[seeMoreComments]-0-[table]-0-|" options:0 metrics:nil views:views]];
//Comment entry input
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[commentInput]-0-|" options:0 metrics:nil views:views]];
commentInputVerticalConstraint = [NSLayoutConstraint constraintWithItem:self.commentEntryInput
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeHeight
multiplier:1.0
constant:commentInputHeight];
if(commentInputBottomConstraint == nil)
{
commentInputBottomConstraint =
[NSLayoutConstraint constraintWithItem:self.commentEntryInput
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom multiplier:1.0
constant:0.0];
}
[self.view addConstraint:commentInputVerticalConstraint];
[self.view addConstraint:commentInputBottomConstraint];
[super updateViewConstraints];
}
Now I have a method that is called when keyBoardWillShow is called. This method animates the comment input control up when the keyboard appears.
(void)animateContentWithKeyboardInfo:(NSDictionary *)keyboardInfo
{
NSNumber *animationDuration = keyboardInfo[ UIKeyboardAnimationDurationUserInfoKey ];
NSValue *keyboardFrameValue = keyboardInfo[ UIKeyboardFrameEndUserInfoKey ];
CGRect keyboardFrame = [keyboardFrameValue CGRectValue];
UIViewAnimationCurve animationCurve = [keyboardInfo[ UIKeyboardAnimationCurveUserInfoKey ] intValue];
UIViewAnimationOptions animationOptions = animationOptionWithCurve(animationCurve);
commentInputBottomConstraint.constant = (keyboardFrame.origin.y - [UIScreen mainScreen].bounds.size.height);
//Increase the veritcal height of the comment input control
commentInputVerticalConstraint.constant = 125;
//Takes into account that the Tab Bar is 50 points, and adjust for this
//value.
if(keyboardAppeared == YES)
{
commentInputBottomConstraint.constant += TAB_BAR_OFFSET;
}
else
{
commentInputBottomConstraint.constant -= TAB_BAR_OFFSET;
}
[self.view layoutIfNeeded];
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:[animationDuration floatValue] delay:0.0 options:animationOptions animations:
^{
[self.view layoutIfNeeded];
} completion:nil];
}
However, when I try to adjust the constant of the of the commentInputVerticalConstraint I receive this error message:
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the `UIView` property `translatesAutoresizingMaskIntoConstraints`)
(
"<NSLayoutConstraint:0x1899fcb0 V:[CommentEntryInput:0x176e5160(50)]>",
"<NSLayoutConstraint:0x1899e5c0 V:[CommentEntryInput:0x176e5160(125)]>"
)
I'm not sure if there is a way for me to "reset" or adjust the constraint to handle when the keyboard appears and then put it back to normal when the keyboard disappears. Any help would be appreciated.
Your problem is that -(void)updateViewConstraints is getting called more than once. So you are creating a new constraint and adding it to the view twice. Try checking if the constraint is nil or not.
I also don't think you need the first [self.view layoutIfNeeded] before the animation change of the constant. When changing constant, just set it then wrap the [self.view layoutIfNeeded] in a animation block to animate to that new value.

UIView auto layout slide in screen or out of screen animation

I can't figured it out how to do slide in/ out animation with auto layout.
I add constraints like this:
NSDictionary *viewsDic = #{#"tmpView" : tmpView};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[tmpView]|" options:0 metrics:nil views:viewsDic]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[tmpView]|" options:0 metrics:nil views:viewsDic]];
[UIView animateWithDuration:.4 animations:^{
[self.view layoutIfNeeded];
}];
but this animates to grow from 0,0 position. how to achieve slide in/out animation?
As far as I understand, you need to get shift-effect. If my assumption is right, you need to manage horizontal or vertical padding manually during animation. And you need to get the reference on horizontal/vertical constraint:
#property (nonatomic, strong) NSLayoutConstraint *topPadding;
#property (nonatomic, strong) NSLayoutConstraint *heightConstraint;
Adding a constraint with initial value so that tmpView is out of visible part of its superview:
self.heightConstraint = [NSLayoutConstraint constraintWithItem:tmpView
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:0.0];
self.topPadding = [NSLayoutConstraint constraintWithItem:tmpView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:self.view.bounds.size.height];
[self.view addConstraint:self.topPadding];
[self.view addConstraint:self.heightConstraint];
Then we need simply to show tmpView with animation:
[self.view layoutIfNeeded];
[UIView animateWithDuration:.4 animations:^{
self.topPadding.constant = 0.0;
self.heightConstraint.constant = self.view.bounds.size.height;
[self.view layoutIfNeeded];
}];
Whit this example tmpView appears from the bottom.
Please ensure that self.topPadding won't conflict with other you constraints
To hide the view you can use something like this:
[self.view layoutIfNeeded];
[UIView animateWithDuration:.4 animations:^{
self.topPadding.constant = self.superview.bounds.size.height;
[self.view layoutIfNeeded];
}];
UPD.: Sometimes you also need to add hight constraints as well. Added use of self.heightConstraint in my example
UPD.: You still need horizontal constraints.
Please leave these lines:
NSDictionary *viewsDic = #{#"tmpView" : tmpView};
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[tmpView]|" options:0 metrics:nil views:viewsDic]];

Programmatically creating "spacing to nearest neighbor" constraint

Part of the screen I'm building includes a section with n views. I'm generating these views on the fly in code--they're simple UIView subclasses.
I'm using AutoLayout constraints for this screen, and I'd like each view to automatically position itself 15px or so below the view above it.
In Xcode it's possible to create a spacing to nearest neighbor constraint, which seems to do exactly what I want.
However, I can't seem to find any examples that show how to create this in code.
Is it possible to create a "spacing to nearest neighbor" constraint programmatically?
I was actually doing some personal exercises of auto-layout and animations when I stumbled over your question and decided to extend my a small demo, which you can download here.
If I have understood you correctly below piece of code can be used for inspiration. With a small effort it could be extended with removal of views too and also with dynamic height of the views.
Please note my code includes a solution with and without animation - the latter is of course more simple.
#import "Demo2ViewController.h"
#interface Demo2ViewController ()
{
NSMutableArray *_viewList;
NSDictionary *_metrics;
}
#end
#implementation Demo2ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[[self view] setBackgroundColor:[UIColor colorWithRed:.95 green:.95 blue:.95 alpha:1.0]];
_metrics = #{#"height": #30, // height of the views being added
#"space": #15}; // space between two views
// the first view
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectNull];
_viewList = [[NSMutableArray alloc] initWithObjects:textView, nil];
textView.text = [NSString stringWithFormat:#"view: %lu", (unsigned long)[_viewList count]];
// a button to add more views
UIButton *buttonAddView = [[UIButton alloc] initWithFrame:CGRectNull];
[buttonAddView setTitle:#"add new view" forState:UIControlStateNormal];
[buttonAddView setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[buttonAddView addTarget:self action:#selector(buttonPushed:) forControlEvents:UIControlEventTouchDown];
NSDictionary *subviews = NSDictionaryOfVariableBindings(textView, buttonAddView);
for (id view in [subviews allValues]) {
[[self view] addSubview:view];
[view setTranslatesAutoresizingMaskIntoConstraints:NO];
}
// initial constraints
[[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[textView]-|" options:0 metrics:nil views:subviews]];
[[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[buttonAddView]-|" options:0 metrics:nil views:subviews]];
[[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[textView(==height)]" options:0 metrics:_metrics views:subviews]];
[[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[buttonAddView]-|" options:0 metrics:nil views:subviews]];
}
-(void)buttonPushed:(UIButton*)button
{
UITextView *prevView = [_viewList lastObject]; // get reference to previous view
// create a new view
UITextView *newView = [[UITextView alloc] initWithFrame:CGRectNull];
[[self view] addSubview:newView];
[newView setTranslatesAutoresizingMaskIntoConstraints:NO];
[_viewList addObject:newView];
newView.text = [NSString stringWithFormat:#"view: %lu", (unsigned long)[_viewList count]];
NSDictionary *subviews = NSDictionaryOfVariableBindings(prevView, newView);
[[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[newView]-|" options:0 metrics:nil views:subviews]];
#if 0
// without animation
[[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[prevView]-space-[newView(==height)]" options:0 metrics:_metrics views:subviews]];
[[self view] layoutIfNeeded];
#else
// with animation
// to begin with the new view gets zero height and no space to previous view
NSArray *tempConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[prevView][newView(==0)]" options:0 metrics:nil views:subviews];
[[self view] addConstraints:tempConstraints];
[[self view] layoutIfNeeded]; // to ensure zero height is the starting point for the animation
[newView setAlpha:0.0f]; // starting point for fade-in
[UIView animateWithDuration:0.25f animations:^{
[[self view] removeConstraints:tempConstraints]; // remove zero height constraint
[[self view] addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[prevView]-space-[newView(==height)]" options:0 metrics:_metrics views:subviews]]; // add final constraints
[newView setAlpha:1.0f]; // fade-in
[[self view] layoutIfNeeded];
}];
#endif
}
#end
You can create a constraint dictionary and a constraint string and apply them programmatically.
Adding items and keys to the dictionary is trivial so I won't deal with that. Just remember every view in the constraint system must be in the dictionary.
Creating the format string is the interesting bit. Presumably you want to add your views under as certain view, say it has the NSString key topView. The first part of the format string looks like
NSString *constraintBase = [NSString stringWithFormat:#"V:topView"];
For each view you want to add, you add to that string
NSString *constraintString = [constraintBase stringByAppendingString:[NSString stringWithFormat:#"-15-%#", viewDictionaryKey]];
Finally apply constraintString as usual, a constructed visual constraint format string.
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:constraintString options:0 metrics:nil views:viewsToConstrain]];
Here the view's which are generated programatically are added to a parent view.
When a view is created its constraints should be added to it.
But the constraints must mapped with the previous view, and so we need to identify the previous view (last view in the parent view)
NSArray *subViewList = [_vwParentView subviews];
UIView *lastView;
if (subViewList.count > 0) {
lastView = [subViewList lastObject];
}
The above code will help to find the last created view.
When Views are created programatically and added as sub views, the views will added as stack for parrentView and hence the view created at last will be the last object in the subViewList array
Note: Assuming that a separate view is assigned as parent view with no subviews initially.
UIView *contentView = [[UIView alloc]init];
NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeWidth multiplier:1.0 constant:initialWidth];
[contentView addConstraint:widthConstraint];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1.0 constant:initialHeight];
[contentView addConstraint:heightConstraint];
contentView.translatesAutoresizingMaskIntoConstraints = NO;
[_vwParentView addSubview:contentView];
NSLayoutConstraint *gapMaintainTopConstraint;
if (lastView == nil) {
gapMaintainTopConstraint = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_vwParentView attribute:NSLayoutAttributeTop multiplier:1.0 constant:15];
}
else
{
gapMaintainTopConstraint = [NSLayoutConstraint constraintWithItem:contentView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:lastView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:15];
}
[_vwParentView addConstraint:gapMaintainTopConstraint];
In case to change the size of the added view in future, it should be achieved by changing its widthConstraint or heightConstraint, only then the constraint which is associated to it (to maintain specific gap) will work. Size should not be changed using frames thereafter.
Meaning - constraint based views should be handled using constraints only.
It is possible to create a "spacing to nearest neighbour" constraint only after the created view is added as a sub view,.
The translatesAutoresizingMaskIntoConstraints property of the created view should be disabled, so that there won't be any conflict of constraints when there is any change in size (of the created view) in future.

UIView Awful Performance

I have built a slide navigation controller which allows the sliding of UIViewController's in a fast and smooth way (Facebook style). I have since added a UIViewController with a child view controller with it's own child view controller, as well as a table view. The lowest child view controller also has a view subviews. This UIViewController has the view that is made visible when the top view is slid away.
I have tested the smoothness both with and without this view controller. Without it the slide runs at a nice 60 frames per second, but with it my device is only managing a choppy 20 to 30 fps.
I have also tried removing subviews which seems to make a slight improvement, but not as much as I would expect. Even when switched out with another fairly complex view controller (without child view controls though) I get much better performance.
I am using auto layout throughout the app, and have come to believe this is the problem. None of my code is being executed whilst this poor sliding is occurring, so I believe it has something to do with the constraints being calculated as more of the view is being shown, but can't be sure.
As to avoid including the whole class, here are the updateViewConstraint methods in the view controller and subviews:
TOP VIEW CONTROLLER
/**
* Called when the view controller’s view needs to update its constraints.
*/
- (void)updateViewConstraints
{
[super updateViewConstraints];
// remove all constraints
[self.view removeConstraints:self.view.constraints];
NSArray *constraints;
// add the table view to the top of the view and the parameters view to the bottom
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(Panel)-[tableView]|"
options:kNilOptions
metrics:#{#"Panel": #(kPanelWidth)}
views:self.viewsDictionary];
[self.view addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[tableView]-|"
options:kNilOptions
metrics:nil
views:self.viewsDictionary];
[self.view addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-(PanelPlus)-[recipeParameters]-|"
options:kNilOptions
metrics:#{#"PanelPlus": #(kPanelWidth + 20)}
views:self.viewsDictionary];
[self.view addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:[recipeParameters(==Height)]|"
options:kNilOptions
metrics:#{ #"Height" : #(kParametersControllerHeight)}
views:self.viewsDictionary];
[self.view addConstraints:constraints];
}
FIRST CHILD VIEW CONTROLLER
/**
* Called when the view controller’s view needs to update its constraints.
*/
- (void)updateViewConstraints
{
[super updateViewConstraints];
// remove all constraints
[self.view removeConstraints:self.view.constraints];
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|[pageView]|" options:kNilOptions
metrics:nil views:self.viewsDictionary];
[self.view addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[pageView]|" options:kNilOptions
metrics:nil views:self.viewsDictionary];
[self.view addConstraints:constraints];
}
SECOND CHILD VIEW CONTROLLER
- (void)updateViewConstraints
{
[super updateViewConstraints];
NSArray *constraints;
// remove all constraints
[self.view removeConstraints:self.view.constraints];
if (self.interfaceOrientation == UIInterfaceOrientationPortrait || self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
{
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(8)-[optionLabel]-[selectionWheel]-[includeExclude(==32)]-|"
options:NSLayoutFormatAlignAllCenterX
metrics:nil
views:self.viewsDictionary];
[self.view addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[selectionWheel]-|"
options:kNilOptions
metrics:nil
views:self.viewsDictionary];
[self.view addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[includeExclude]-|"
options:kNilOptions
metrics:nil
views:self.viewsDictionary];
[self.view addConstraints:constraints];
}
else
{
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[selectionWheel]-|" options:kNilOptions
metrics:nil views:self.viewsDictionary];
[self.view addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[optionLabel]-[selectionWheel]-(Balance)-|"
options:NSLayoutFormatAlignAllCenterY
metrics:#{#"Balance": #(self.optionLabel.bounds.size.width + 40)}
views:self.viewsDictionary];
[self.view addConstraints:constraints];
}
}
CUSTOM UICONTROL (SUBVIEW OF SECOND CHILD VIEW CONTROLLER)
/**
* Update constraints for the view.
*/
- (void)updateConstraints
{
[super updateConstraints];
[self removeConstraints:self.constraints];
[self.excludeButton removeConstraints:self.excludeButton.constraints];
[self.includeButton removeConstraints:self.includeButton.constraints];
NSArray *constraints;
NSLayoutConstraint *constraint;
// add everything to fill the bounds
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"V:|-(==6)-[excludeButton]-(==6)-|"
options:kNilOptions
metrics:nil
views:self.viewsDictionary];
[self addConstraints:constraints];
constraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[excludeButton][optionLabel][includeButton]|"
options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom
metrics:nil
views:self.viewsDictionary];
[self addConstraints:constraints];
// make the exclude and include buttons square
constraint = [NSLayoutConstraint constraintWithItem:self.excludeButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.excludeButton attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f];
[self.excludeButton addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:self.includeButton attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.includeButton attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f];
[self.includeButton addConstraint:constraint];
}
The implementation of the top UIViewController is here.

Resources