What is the correct way to change constraint constants - objective-c

I have to alter constraint but by changing constraint constants,
I get duplicates - Xcode gives a warning.
I can see that one constraint is the old one and the other is the new one,
and their memory addresses are different.
What is the correct way to create and setup views to handle constraint changes?
I my example I have a mainView which added to self.view, the provided view
when you extend UIViewController. "self.view" is provided and has no constraints set.
Main MainView is my container and I want to adjust its height to be above the keyboard whenever the keyboard appears.
viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
_mainView = [UIView new];
_mainView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:_mainView];
}
viewWillLayoutSubviews:
-(void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
//moved to viewDidLoad
//self.mainView.translatesAutoresizingMaskIntoConstraints = NO;
//top
[[self view] addConstraint:[NSLayoutConstraint constraintWithItem:_mainView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:0]];
//bottom
_mainBottomContraint = [NSLayoutConstraint constraintWithItem:_mainView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:_keyboardOffset];
[[self view] addConstraint:_mainBottomContraint];
//left
[[self view] addConstraint:[NSLayoutConstraint constraintWithItem:_mainView
attribute:NSLayoutAttributeLeft
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeft
multiplier:1.0
constant:0]];
//right
[[self view] addConstraint:[NSLayoutConstraint constraintWithItem:_mainView
attribute:NSLayoutAttributeRight
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeRight
multiplier:1.0
constant:0]];
-
Whenever I alter a constraint constant I get duplicate constraints,
viewWillLayoutSubviews gets called again and recreates the constraints.
How does one change the constraints without re-creation? Or what is the correct pattern to use here.
keyboardWillShow - changes the constraint (setConstant)
- (void)keyboardWillShow:(NSNotification*)aNotification {
if (![_chatTextField isFirstResponder]) {
return;
}
CGSize tabBarSize = [[[self tabBarController] tabBar] bounds].size;
NSDictionary* info = [aNotification userInfo];
NSTimeInterval duration = [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];
CGSize kbSize = [info[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect bkgndRect = _mainView.frame;
bkgndRect.size.height -= kbSize.height-tabBarSize.height;
//animate with keyboard
_keyboardOffset = -kbSize.height-tabBarSize.height;
[_mainBottomContraint setConstant:_keyboardOffset];
[self.view setNeedsLayout];
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
[_mainView layoutIfNeeded];
} completion:nil];
}
LOGS
Constraint 1 at memory address 0x174286450
Constraint 2 at memory address 0x174288660
(
"<NSLayoutConstraint:0x174286450 UIView:0x14fd5e5b0.bottom == UIView:0x14fe5edd0.bottom - 271 (active)>",
"<NSLayoutConstraint:0x174288660 UIView:0x14fd5e5b0.bottom == UIView:0x14fe5edd0.bottom (active)>"
)

In my opinions,you add the _mainBottomContraint twice.First,you creat a _mainBottomContraint and retain it,when the keyboard change,the _mainBottomContraint.constaints changes,and if the view in self.view.subviews change the frame,the system will post a notification,and the viewcontroller will recieve it,and call viewWillLayoutSubviews,like the view will call layoutSubviews.So you creat a _mainBottomContraint,so now,there are two bottomContraint and you get a warning.
You should add the contraints only once,you can add them in viewDidLoad function,and it will be good.

Call
subview.translatesAutoresizingMaskIntoConstraints = NO;
on the subView BEFORE adding it to another view. Otherwise some constraints get created automatically leading to warnings.
- (void)viewDidLoad {
[super viewDidLoad]; _mainView = [UIView new];
self.mainView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:_mainView];
}
Then save references of your created constraints (like you do) and change them whenever neccesary.

Related

Why my constraints doesn't work in my xib file

I am trying to add a button to a UIstackview, programmatically. All this is in fitxero XIB.
  The button is created correctly, but when adding the constraints I get the following error:
2020-05-21 17:51:08.328369+0200 eWAS[3391:567586] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view?
That's illegal. constraint: < NSLayoutConstraint:0x282362b70 V:|-(0)-[UIButton:0x11c225a60'button'] (active, names: '|':UIStackView:0x11bfc13f0 ) > view:< UIButton: 0x11c225a60; frame = (0 0; 30 150); opaque = NO; layer = < CALayer: 0x2802e4220 > >'
-(void) configureTabsWithTexts: (NSArray *) tabs{
NSInteger tag = 0;
UIButton *currentButton = [UIButton buttonWithType:UIButtonTypeSystem];
[currentButton setTitle:#"Button1" forState:UIControlStateNormal];
[currentButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[currentButton setTag:tag];
[currentButton.titleLabel setFont:[UIFont systemFontOfSize:20]];
[currentButton.titleLabel setTextColor:[UIColor whiteColor]];
[currentButton setFrame:CGRectMake(0, 0, 30, 150)];
currentButton.backgroundColor = [UIColor blackColor];
[self.stackViewForButtons addSubview:currentButton];
[currentButton setTranslatesAutoresizingMaskIntoConstraints:NO];
NSMutableArray <NSLayoutConstraint *> *arrayConstraints = [[NSMutableArray alloc] init];
currentButton.translatesAutoresizingMaskIntoConstraints = false;
[currentButton addSubview:self.stackViewForButtons];
[currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.stackViewForButtons
attribute:NSLayoutAttributeTop
multiplier:1
constant:0]];
[currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:currentButton.superview
attribute:NSLayoutAttributeBottom
multiplier:1
constant:0]];
[currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1
constant:50]];
[currentButton addConstraint: [NSLayoutConstraint constraintWithItem:currentButton
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:currentButton.superview
attribute:NSLayoutAttributeLeading
multiplier:1
constant:0]];
}
You have this line:
[self.stackViewForButtons addSubview:currentButton];
which seems fine, but then later you are doing:
[currentButton addSubview:self.stackViewForButtons];
which seems backwards and is probably the source of your problem. Try removing that latter line and see if it works. I doubt you want a UIButton to have a stack view as a subview. With both lines in place, there is a circular reference, which UIView probably figures out and removes the original superview of the UIButton, meaning that is nil when you are creating the later constraints (or maybe it removes the superview/subview relationship altogether).
As an aside, if you are using an actual UIStackView which it looks like you are, you shouldn't need any of these constraints done by hand. The entire point of UIStackView is to generate all those constraints for you. In that case, simply call:
[self.stackViewForButtons addArrangedSubview:currentButton];
[currentButton setTranslatesAutoresizingMaskIntoConstraints:NO];
and you should be done, provided you have configured the stack view correctly. Maybe you need the width constraint on each one, not sure. While you can add non-arranged subviews to a UIStackView, that should be rare. And even if that is intended in this case, you may be better off adding another UIStackView as a subview, then adding the buttons to that.

Adjusting subviews to keep their size using auto layout

I have a UIView that contains subviews that looks like this:
This view was originally designed with 320 width in mind. iPhone 5s and lower. However I am now adapting it to work with iPhone 6+
The issue I am facing is getting the subviews width to grow to accommodate the extra space on the left and right of their super view. I can only seem to get the centre views width to grow, however not the out views. What constraints would I need to apply or change in order to get all views to grow a little to accommodate the extra space on the sides?
Hi!
If you design your view in interface builder, you may try this:
1- set all views to specific width and height
2- the view at the corner add pin to the edge with static value.
3- the view in the middle add pin to top or bottom, and add align constraint to horizontal centre of superview
Not sure if this help, Just try to answer!
Here is a complete example of how to achieve this programmatically (with dummy views):
// Simple example demonstrating the below screenshots
// Create containers to hold each row of subviews
UIView *container1 = [UIView new];
container1.translatesAutoresizingMaskIntoConstraints = NO;
container1.backgroundColor = [UIColor redColor];
UIView *container2 = [UIView new];
container2.translatesAutoresizingMaskIntoConstraints = NO;
container2.backgroundColor = [UIColor orangeColor];
// Create the subviews
UIView *v1 = [UIView new];
v1.translatesAutoresizingMaskIntoConstraints = NO;
v1.backgroundColor = [UIColor grayColor];
UIView *v2 = [UIView new];
v2.translatesAutoresizingMaskIntoConstraints = NO;
v2.backgroundColor = [UIColor blackColor];
UIView *v3 = [UIView new];
v3.translatesAutoresizingMaskIntoConstraints = NO;
v3.backgroundColor = [UIColor greenColor];
UIView *v4 = [UIView new];
v4.translatesAutoresizingMaskIntoConstraints = NO;
v4.backgroundColor = [UIColor purpleColor];
UIView *v5 = [UIView new];
v5.translatesAutoresizingMaskIntoConstraints = NO;
v5.backgroundColor = [UIColor blueColor];
UIView *v6 = [UIView new];
v6.translatesAutoresizingMaskIntoConstraints = NO;
v6.backgroundColor = [UIColor yellowColor];
// add the subviews
[container1 addSubview:v1];
[container1 addSubview:v2];
[container1 addSubview:v3];
[container2 addSubview:v4];
[container2 addSubview:v5];
[container2 addSubview:v6];
// Add the containers to the root view (in this case self.view)
[self.view addSubview:container1];
[self.view addSubview:container2];
// Add constraints for the containers
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[container1]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(container1)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[container2]-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(container2)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-64.0-[container1(==100)]-[container2(==container1)]" options:0 metrics:nil views:NSDictionaryOfVariableBindings(container1, container2)]];
// Add constraints in both VFL and regular NSConstraints to the subviews of container 1
[container1 addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[v1]-[v2(==v1)]-[v3(==v1)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(v1,v2,v3)]];
[container1 addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[v1]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(v1)]];
[container1 addConstraint:[NSLayoutConstraint constraintWithItem:v2 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:v1 attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f]];
[container1 addConstraint:[NSLayoutConstraint constraintWithItem:v2 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:container1 attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f]];
[container1 addConstraint:[NSLayoutConstraint constraintWithItem:v3 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:v1 attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f]];
[container1 addConstraint:[NSLayoutConstraint constraintWithItem:v3 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:container1 attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f]];
// Add constraints in both VFL and regular NSConstraints to the subviews of container 2
[container2 addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[v4]-[v5(==v4)]-[v6(==v4)]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(v4,v5,v6)]];
[container2 addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[v4]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(v4)]];
[container2 addConstraint:[NSLayoutConstraint constraintWithItem:v5 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:v4 attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f]];
[container2 addConstraint:[NSLayoutConstraint constraintWithItem:v5 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:container2 attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f]];
[container2 addConstraint:[NSLayoutConstraint constraintWithItem:v6 attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:v4 attribute:NSLayoutAttributeHeight multiplier:1.0f constant:0.0f]];
[container2 addConstraint:[NSLayoutConstraint constraintWithItem:v6 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:container2 attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f]];
Attached are screenshots on iPhone 5s, iPhone 6 and iPhone 6 Plus respectively:
iPhone 5s
iPhone 6
iPhone 6 Plus
I hope this at least point you in the right direction =)
disable autolayout and use autoresizing masks in the interface builderHandling Layout Changes Automatically Using Autoresizing Rules

UIView not animating correctly when UILabel is added to it

I'm animating a custom view off screen using a constraint on view's top edge.
The view is:
#implementation MyView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[UIColor yellowColor]];
_label = [UILabel new];
[_label setTranslatesAutoresizingMaskIntoConstraints:NO];
_label.text = #"text";
[self addSubview:_label];
[self updateConstraints];
}
return self;
}
- (void)updateConstraints
{
NSDictionary *views = NSDictionaryOfVariableBindings(_label);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-[_label]"
options:NSLayoutFormatAlignAllLeft
metrics:nil
views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-[_label]"
options:NSLayoutFormatAlignAllCenterY
metrics:nil
views:views]];
[super updateConstraints];
}
#end
The constraint for animating myView on its parent view is:
_myViewTopConstraint = [NSLayoutConstraint constraintWithItem:_myView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0
constant:-kMyViewVisibleHeight];
[self.view addConstraint:_myViewTopConstraint];
The animation on the top edge constraint is:
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
self.myViewTopConstraint.constant = kScreenHeight;
[self.myView layoutIfNeeded];
} completion:nil];
When the label and constraints in MyView is commented out, the animation works perfectly. But when the label and constraints are there, the animation is sped up significantly, maybe 5x or more.
Why does this happen? Anyone know how to fix it?
Figured it out. layoutIfNeeded must be called on myView's parent view in the animation block.
[self.myView layoutIfNeeded];
changed to
[self.view layoutIfNeeded];

Autolayout when adding subview to UIWindow

I am creating a customalertview that needs to be added as a subview to UIWindow. I've setup the constraints for it's subviews correctly but I'm confused as to when/how to set the constraints on the view itself in relation to the window.
I would like the width of the alertview to be 70% of the width of the screen. The height is already in relation to it's subviews.
- (void)show {
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
[window addSubview:self];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:[UIApplication sharedApplication].keyWindow attribute:NSLayoutAttributeWidth multiplier:0.7 constant:0]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_messageLabel attribute:NSLayoutAttributeBottom multiplier:1.0 constant:10]];
[self addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:(_imageView.image ? _imageView : _titleLabel) attribute:NSLayoutAttributeTop multiplier:1.0 constant:-10]];
}
What am I doing wrong? I am getting the following error message:
NSLayoutConstraint:0x181cd7c0 WFSoftAlertView:0x16e384c0.width == 0.7*UIWindow:0x16e7c8c0.width>
When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled.
WFSoftAlertView.translatesAutoresizingMaskIntoConstraints=NO;
NSDictionary *views = NSDictionaryOfVariableBindings(WFSoftAlertView);
float width30 = self.view.frame.size.width*.3;
width30 = width30/2; // divided by 2 for padding of its left/rigth
NSString *str =[NSString stringWithFormat:#"%f",width30];
NSDictionary *metrics = #{#"width":str};
[self.view addSubview:WFSoftAlertView];
//add the WFSoftAlertView in center(x) of superview with a padding of "width"
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|-width-[WFSoftAlertView]-width-|" options:NSLayoutFormatAlignAllTop | NSLayoutFormatAlignAllBottom metrics:metrics views:views]];
// if you want center(y)
NSLayoutConstraint *centerY = [NSLayoutConstraint
constraintWithItem:WFSoftAlertView
attribute:NSLayoutAttributeCenterY
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeCenterY
multiplier:1.0f
constant:0.f];
Try changing your constraintWithItem from
self
to
self.view

iOS Dim background when a view is shown

In my main view, I do some gesture action causing some new view to be shown. At this time I want to dim the entire background (except this new view) as a good UI practice. In HTML, Javascript it looks like so - How do I get this same effect in iOS ?
Lay a UIView over the background, set its background to [UIColor blackColor] and set its opacity to like 0.6. Then add that UIView to the parent view.
This'll dim out the background AND intercept any taps to background controls.
While Dan's suggestion is on target, you cannot use a modal view controller in this case because a typical modal covers the entire screen, blocking the parent view controller, even if you have the background of your view as transparent (you'll see whatever you have in the application's UIWindow).
If you are doing this on the iPad there are 2 modal presentation styles (UIViewModalPresentationStylePageSheet and UIViewModalPresentationStyleFormSheet) that can do something similar, but those will not work on an iPhone or iPod Touch.
Add the "shadow" view, with the dark background and partial opacity and whatever view you want to be in the foreground, to the view controller's view directly. You can animate them in using standard UIView animation blocks, or CoreAnimation.
Another note, if you want to intercept touches to that shadow view you can either make it a giant button, subclass UIView to override one of the touch methods like touchesEnded: or change it to a UIControl which can receive touch events like a UIButton, but without the extra options for text, shadows, states etc.
The above two answers work if the new view has it's own 'background', i.e. has no transparency. The problem that led me here cannot be solved that way though, what I was trying to do is this: I'm running an AVCaptureSession on my screen with the usual AVCaptureVideoPreviewLayer to display video in real time. I want to select a part of the screen (to later do something with only this part), and when this part is selected want to dim the rest of the video preview. This is what it looks like:
This is how I solved this: A new view is created depending on where the screen is touched and added as a subview of the video preview view. Then, I create 4 additional, non-overlapping rectangular subviews with the before-mentioned background color and opacity to cover the rest of the screen. I explicitly need all these views not to be subviews of the main view, because I need the ability to touch the screen somewhere else and change the selected area.
I'm sure there are more elegant ways to solve this, so if someone knows how please comment...
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UIGestureRecognizerDelegate>
{
UIView *mainView;
UIView *dimBackgroundUIView;
UIView *customView;
UIButton *btn;
}
#end
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
mainView = [[UIView alloc] init];
mainView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:mainView];
[self addConstraintsForMainView];
btn = [[UIButton alloc] initWithFrame:CGRectMake(200, 200, 100, 30)];
[btn setTitle:#"Button" forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor blueColor]];
[btn addTarget:self action:#selector(showCustomView_Action:) forControlEvents:UIControlEventTouchUpInside];
[mainView addSubview:btn];
dimBackgroundUIView = [[UIView alloc] init];
dimBackgroundUIView.backgroundColor = [UIColor blackColor];
dimBackgroundUIView.alpha = 0.2;
}
-(void)removeCustomViewsFromSuperView {
if(dimBackgroundUIView)
[dimBackgroundUIView removeFromSuperview];
if(customView)
[customView removeFromSuperview];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)showCustomView_Action:(id)sender {
customView = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 80, 80)];
customView.backgroundColor = [UIColor redColor];
[self.view addSubview:dimBackgroundUIView];
[self addConstraintsForDimView];
[self.view addSubview:customView];
UITapGestureRecognizer *tapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(removeCustomViewsFromSuperView)];
tapped.delegate=self;
tapped.numberOfTapsRequired = 1;
[customView addGestureRecognizer:tapped];
}
-(void) addConstraintsForDimView {
[dimBackgroundUIView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:dimBackgroundUIView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:dimBackgroundUIView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:dimBackgroundUIView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:dimBackgroundUIView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:0]];
}
-(void) addConstraintsForMainView {
[mainView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:mainView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:mainView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:mainView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:mainView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1 constant:0]];
}
#end
note: you can optimise the code by using graphical interface on Xcode but i had to write code programmatically to be able to test it
so the idea is to:
create UIView name it what you want (dimBackgroundUIView) than set
the backgroundcolor as Black and set alfa to 0.1 or 0.2 or....
add this 2 line of code when you need to dim the background:[self.view addSubview:dimBackgroundUIView];
[self addConstraintsForDimView];
and add this 2 line of code when you want to remove the dimming
background: if(dimBackgroundUIView) [dimBackgroundUIView removeFromSuperview];