【问题标题】:Autolayout layoutIfNeeded is breaking constraintsAutolayout layoutIfNeeded 打破了约束
【发布时间】:2016-12-15 16:23:32
【问题描述】:

我正在 xib 文件中创建以下视图。 有两个约束,我一次想要一个,所以我激活一个并停用另一个约束。

其中一个约束是视图(顶层视图)view.bottom == inputView.bottom。当文本视图中的用户输入正确时,将启用此约束。如果用户输入一些特殊字符,则会显示错误消息,并且此约束被停用,另一个约束 view.bottom == errorLabel.bottom 被激活。最初这两个约束都存在于 xib 文件中,但view.bottom == errorLabel.bottom 设置为750 优先级,view.bottom == input View.bottom 设置为所需的优先级1000。这是为了避免冲突的约束。

现在,当用户键入一些输入时,我会执行以下操作。

[NSLayoutConstraint deactivateConstraints:@[self.inputViewConstraint, self.inputViewWithErrorConstraint]];

        self.inputViewConstraint.active = (result == NBValidationResultOK);
        self.inputViewWithErrorConstraint.active = !self.inputViewConstraint.active;

        [UIView animateWithDuration:0.1 animations:^{
            [self layoutIfNeeded];
        }];


inputViewConstraint -----> view.bottom == InputView.bottom
inputViewWithErrorConstraint -----> view.bottom == errorLabel.bottom

当我执行上述代码时,调试器会给我打破约束警告。

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-08-09 17:11:45.181 NB[17707:1811620] Unable to simultaneously satisfy constraints.
    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) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x7faf12ac8850 h=-&- v=-&- UIView:0x7faf12ac41f0.width == NBSendMoneyTextInputView:0x7faf128c8ab0.width>",
    "<NSLayoutConstraint:0x7faf12a74020 H:|-(16)-[NBUISecondaryLabel:0x7faf12ac3560'SecondaryLabel']   (Names: '|':UIView:0x7faf12ac31e0 )>",
    "<NSLayoutConstraint:0x7faf12a4a950 UITextView:0x7faf140b7400.leading == NBUISecondaryLabel:0x7faf12ac3560'SecondaryLabel'.leading>",
    "<NSLayoutConstraint:0x7faf12a76630 H:[UITextView:0x7faf140b7400]-(16)-|   (Names: '|':UIView:0x7faf12ac31e0 )>",
    "<NSLayoutConstraint:0x7faf12a2ae80 H:[UIView:0x7faf12ac31e0]-(0)-|   (Names: '|':UIView:0x7faf12ac41f0 )>",
    "<NSLayoutConstraint:0x7faf12a2aed0 H:|-(0)-[UIView:0x7faf12ac31e0]   (Names: '|':UIView:0x7faf12ac41f0 )>",
    "<NSLayoutConstraint:0x7faf12ac5ac0 '_UITemporaryLayoutWidth' H:[NBSendMoneyTextInputView:0x7faf128c8ab0(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7faf12a4a950 UITextView:0x7faf140b7400.leading == NBUISecondaryLabel:0x7faf12ac3560'SecondaryLabel'.leading>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-08-09 17:11:45.182 NB[17707:1811620] Unable to simultaneously satisfy constraints.
    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) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x7faf12ac88f0 h=-&- v=-&- UIView:0x7faf12ac41f0.height == NBSendMoneyTextInputView:0x7faf128c8ab0.height>",
    "<NSLayoutConstraint:0x7faf12aa8b20 V:[NBUISeparatorView:0x7faf12ac3990(2)]>",
    "<NSLayoutConstraint:0x7faf12a64b10 V:|-(18)-[NBUISecondaryLabel:0x7faf12ac3560'SecondaryLabel']   (Names: '|':UIView:0x7faf12ac31e0 )>",
    "<NSLayoutConstraint:0x7faf12a368b0 V:[NBUISecondaryLabel:0x7faf12ac3560'SecondaryLabel']-(4)-[UITextView:0x7faf140b7400]>",
    "<NSLayoutConstraint:0x7faf12a41f60 V:[UITextView:0x7faf140b7400]-(2)-[NBUISeparatorView:0x7faf12ac3990]>",
    "<NSLayoutConstraint:0x7faf12a3e240 V:[NBUISeparatorView:0x7faf12ac3990]-(0)-|   (Names: '|':UIView:0x7faf12ac31e0 )>",
    "<NSLayoutConstraint:0x7faf12a211e0 V:|-(0)-[UIView:0x7faf12ac31e0]   (Names: '|':UIView:0x7faf12ac41f0 )>",
    "<NSLayoutConstraint:0x7faf12a9ba30 V:[UIView:0x7faf12ac31e0]-(0)-|   (Names: '|':UIView:0x7faf12ac41f0 )>",
    "<NSLayoutConstraint:0x7faf12ac5bf0 '_UITemporaryLayoutHeight' V:[NBSendMoneyTextInputView:0x7faf128c8ab0(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7faf12aa8b20 V:[NBUISeparatorView:0x7faf12ac3990(2)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-08-09 17:11:45.196 NB[17707:1811620] Unable to simultaneously satisfy constraints.
    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) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x7faf12ac88f0 h=-&- v=-&- UIView:0x7faf12ac41f0.height == NBSendMoneyTextInputView:0x7faf128c8ab0.height>",
    "<NSLayoutConstraint:0x7faf12a64b10 V:|-(18)-[NBUISecondaryLabel:0x7faf12ac3560'SecondaryLabel']   (Names: '|':UIView:0x7faf12ac31e0 )>",
    "<NSLayoutConstraint:0x7faf12a368b0 V:[NBUISecondaryLabel:0x7faf12ac3560'SecondaryLabel']-(4)-[UITextView:0x7faf140b7400]>",
    "<NSLayoutConstraint:0x7faf12a41f60 V:[UITextView:0x7faf140b7400]-(2)-[NBUISeparatorView:0x7faf12ac3990]>",
    "<NSLayoutConstraint:0x7faf12a3e240 V:[NBUISeparatorView:0x7faf12ac3990]-(0)-|   (Names: '|':UIView:0x7faf12ac31e0 )>",
    "<NSLayoutConstraint:0x7faf12a211e0 V:|-(0)-[UIView:0x7faf12ac31e0]   (Names: '|':UIView:0x7faf12ac41f0 )>",
    "<NSLayoutConstraint:0x7faf12a9ba30 V:[UIView:0x7faf12ac31e0]-(0)-|   (Names: '|':UIView:0x7faf12ac41f0 )>",
    "<NSLayoutConstraint:0x7faf12ac5bf0 '_UITemporaryLayoutHeight' V:[NBSendMoneyTextInputView:0x7faf128c8ab0(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7faf12a368b0 V:[NBUISecondaryLabel:0x7faf12ac3560'SecondaryLabel']-(4)-[UITextView:0x7faf140b7400]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

请注意,这些警告只有在我调用 layoutIfNeeded() 方法时才会出现。

在我看来,没有相互冲突的约束。但是,如果有人可以帮助我,那将非常感激。

【问题讨论】:

  • 如果需要,您不应为布局设置动画。尝试为恒定变化设置动画!
  • @TejaNandamuri animate layoutIfNeeded 是正确的方法。约束变化是不可动画的。

标签: ios objective-c autolayout storyboard xib


【解决方案1】:

在打开某些约束之前,您必须将活动标志设置为 false。示例:

self.inputViewConstraint.active = false
self.inputViewWithErrorConstraint.active = false
self.inputViewConstraint.active = result == NBValidationResultOK
self.inputViewWithErrorConstraint.active = !self.inputViewConstraint.active

如果您同时打开两个约束,您将收到警告。

【讨论】:

    【解决方案2】:

    作为建议:

    您可以将其中一个约束更改为低优先级,

    约束激活状态之前发生了哪些变化:

    在您的情况下,低优先级约束应该是self.inputViewConstraintself.inputViewWithErrorConstraint(不能同时使用两者)。

    【讨论】:

    • 嗨,我有这个想法,但更改优先级不是我的选择。对不起,我应该在我的问题中提到这一点。
    • 只是好奇,优先做什么?
    • 似乎在调用layoutIfNeeded 之后,self.inputViewConstraintself.inputViewWithErrorConstraint 同时处于活动状态,然后导致控制台中显示冲突。将其中一个约束更改为低优先级。只是说当这个约束发生冲突时,解除低优先级的约束来解决冲突。
    猜你喜欢
    • 2014-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    相关资源
    最近更新 更多