更改约束常量的正确方法是什么

时间:2021-12-12 10:50:49

I have to alter constraint but by changing constraint constants, I get duplicates - Xcode gives a warning.

我必须更改约束,但通过更改约束常量,我得到重复 - Xcode给出警告。

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.

我的示例我有一个mainView添加到self.view,扩展UIViewController时提供的视图。提供“self.view”并且没有设置约束。

Main MainView is my container and I want to adjust its height to be above the keyboard whenever the keyboard appears.

主MainView是我的容器,我想在键盘出现时将其高度调整到键盘上方。

viewDidLoad:

viewDidLoad中:

- (void)viewDidLoad {

   [super viewDidLoad];

   _mainView = [UIView new];
   _mainView.translatesAutoresizingMaskIntoConstraints = NO;
   [self.view addSubview:_mainView];
}

viewWillLayoutSubviews:

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.

每当我更改约束常量时,我​​都会获得重复约束,再次调用viewWillLayoutSubviews并重新创建约束。如何在不重新创建的情况下改变约束?或者在这里使用的正确模式是什么。

keyboardWillShow - changes the constraint (setConstant)

keyboardWillShow - 更改约束(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

约束1在内存地址0x174286450

Constraint 2 at memory address 0x174288660

约束2在内存地址0x174288660

(
"<NSLayoutConstraint:0x174286450 UIView:0x14fd5e5b0.bottom == UIView:0x14fe5edd0.bottom - 271   (active)>",
"<NSLayoutConstraint:0x174288660 UIView:0x14fd5e5b0.bottom == UIView:0x14fe5edd0.bottom   (active)>"
)

2 个解决方案

#1


1  

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.

在我看来,你添加了_mainBottomContraint两次。首先,你创建一个_mainBottomContraint并保留它,当键盘改变时,_mainBottomContraint.constaints改变,如果self.view.subviews中的视图改变了框架,系统将发布一个通知,并且viewcontroller将接收它,并调用viewWillLayoutSubviews,就像视图将调用layoutSubviews.So你创建一个_mainBottomContraint,所以现在,有两个bottomContraint,你得到一个警告。你应该只添加一次约束,你可以在viewDidLoad函数中添加它们,它会很好。

#2


0  

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.

然后保存您创建的约束的引用(就像您一样),并在需要时更改它们。

#1


1  

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.

在我看来,你添加了_mainBottomContraint两次。首先,你创建一个_mainBottomContraint并保留它,当键盘改变时,_mainBottomContraint.constaints改变,如果self.view.subviews中的视图改变了框架,系统将发布一个通知,并且viewcontroller将接收它,并调用viewWillLayoutSubviews,就像视图将调用layoutSubviews.So你创建一个_mainBottomContraint,所以现在,有两个bottomContraint,你得到一个警告。你应该只添加一次约束,你可以在viewDidLoad函数中添加它们,它会很好。

#2


0  

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.

然后保存您创建的约束的引用(就像您一样),并在需要时更改它们。