安全更改NSLayoutConstraint常量值

时间:2019-06-19 08:40:37

标签: ios swift autolayout nslayoutconstraint

我对UIView对象有底部约束,我想更改它的值。完成后,视图确实可以正确显示,但是,我在控制台中看到错误日志;

[LayoutConstraints] 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. 
(
    "<NSLayoutConstraint:0x600003cbe670 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom + 306   (active)>",
    "<NSLayoutConstraint:0x600003c8cbe0 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom - 10   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600003cbe670 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom + 306   (active)>

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

我的代码是:

private func setupKeyboard(){
    keyboard.delegate = self
    view.addSubview(keyboard)
    keyboardBottomConstraint = keyboard.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: keyboard.expectedHeight())
    keyboard.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    keyboardBottomConstraint.isActive = true
  }

  private func showKeyboard(){
    let bottomOffset: CGFloat = 10
    keyboardBottomConstraint.constant = -bottomOffset
  }

因此,在我setupKeyboard之后,没有错误并且屏幕上没有可见的视图,然后,在我调用showKeyboard之后,它变得可见了,但是出现了错误。

3 个答案:

答案 0 :(得分:1)

设置底部约束优先级值为High(750)

答案 1 :(得分:1)

有错误/警告消息按住键:

np.repeat

如您所见,( "<NSLayoutConstraint:0x600003cbe670 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom + 306 (active)>", "<NSLayoutConstraint:0x600003c8cbe0 PSBApp.KeyboardView:0x7fc5f760e010.bottom == UIView:0x7fc5f4503090.bottom - 10 (active)>" ) 具有 两个 底部约束,它们不能同时有效。

根据OP的评论,KeyboardView被无意中调用了两次,导致2个底部约束。

答案 2 :(得分:0)

您可以自动使用layoutIfNeeded和setNeedsLayout:

layoutIfNeeded强制接收方在需要时立即布局其子视图。

假设您已覆盖layoutSubviews,并且UIKit认为您的视图出于任何原因都需要布局(例如,在处理某些用户操作时调用setNeedsLayout)。然后,将立即调用您的自定义layoutSubviews方法,而不是通常在常规UIKit运行循环事件序列中(通常在事件处理之后,但在drawRect:之前)调用它。

为什么可能需要在单个运行循环中调用layoutIfNeeded的示例:

您调整包含表视图和自定义布局的自定义视图的大小。设置了setNeedsLayout,以便稍后调用layoutSubviews。 在处理用户事件时,控制器对象要求表格视图滚动到某个特定的单元格。 您的自定义视图对layoutSubviews中的表视图执行一些自定义大小调整,以改变表视图​​的大小。 问题在于,当控制器要求表格视图滚动(步骤2)时,表格视图的边界已过时。更新的边界将仅稍后在表格视图上设置(步骤3)。在layoutSubviews完成之后,控制器希望表视图滚动到的内容实际上可能不可见。然后,解决方案是让控制器在知道可能发生的情况下调用layoutIfNeeded。