Wayne
Wayne

Reputation: 3519

What is the correct way to change constraint constants

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)>"
)

Upvotes: 0

Views: 1051

Answers (2)

zacks
zacks

Reputation: 84

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.

Upvotes: 1

Pat_Morita
Pat_Morita

Reputation: 3535

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.

Upvotes: 0

Related Questions