iOS 8 自定义键盘:更改高度而不发出警告“无法同时满足约束...”

Posted

技术标签:

【中文标题】iOS 8 自定义键盘:更改高度而不发出警告“无法同时满足约束...”【英文标题】:iOS 8 Custom Keyboard: Changing the height without warning 'Unable to simultaneously satisfy constraints...' 【发布时间】:2014-10-26 03:20:22 【问题描述】:

关于如何更改自定义键盘高度有几个 SO 答案。其中一些工作例如here,但那些工作导致约束冲突错误打印到控制台输出:

Unable to simultaneously satisfy constraints... 
Will attempt to recover by breaking constraint...

这是我设置自定义键盘高度的非常简单的键盘控制器(是 Swift):

class KeyboardViewController: UIInputViewController 
    private var heightConstraint: NSLayoutConstraint?
    private var dummyView: UIView = UIView()

    override func updateViewConstraints() 
        super.updateViewConstraints()

        if self.view.frame.size.width == 0 || self.view.frame.size.height == 0 || heightConstraint == nil 
            return
        
        inputView.removeConstraint(heightConstraint!)
        heightConstraint!.constant = UIInterfaceOrientationIsLandscape(self.interfaceOrientation) ? 180 : 200
        inputView.addConstraint(heightConstraint!)
    

    override func viewDidLoad() 
        super.viewDidLoad()
        self.dummyView.setTranslatesAutoresizingMaskIntoConstraints(false)
        self.view.addSubview(self.dummyView)

        view.addConstraint(NSLayoutConstraint(item: self.dummyView, attribute: .Left, relatedBy: .Equal, toItem: self.view, attribute: .Left, multiplier: 1.0, constant: 0.0))
        view.addConstraint(NSLayoutConstraint(item: self.dummyView, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1.0, constant: 0.0))

        heightConstraint = NSLayoutConstraint(item: view, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 0.0)
    

这会产生烦人的输出错误,即我在 updateViewConstraints 中添加的约束 heightConstraint 与标识为 UIView-Encapsulated-Layout-Height 的约束冲突。

我尝试删除 updateViewConstraints 中的冲突常量 (UIView-Encapsulated-Layout-Height),如下所示:

let defaultHeightConst = inputView.constraints().filter() c in (c as? NSLayoutConstraint)?.identifier == "UIView-Encapsulated-Layout-Height".first as? NSLayoutConstraint
if defaultHeightConst != nil 
    inputView.removeConstraint(defaultHeightConst!

这没有帮助,输出警告仍然存在。我该如何解决这个问题?具体来说,我该怎么做才能摆脱输出的错误信息?

【问题讨论】:

你摆脱了输出警告??? @Ezimet 是的,不出所料,我摆脱了输出警告。非常令人惊讶的是,优先级为 990 的常量仍然不会被更高优先级的默认高度常量(之前与之冲突)覆盖。愿意解释一下为什么对我来说是这样吗? 【参考方案1】:

尝试将 heightConstraint 的优先级设置为小于 1000。例如 blow :

heightConstraint.priority = 990

heightConstraint.priority = 999

【讨论】:

heightConstraint = 990 选项确实有效,heightConstraint = UILayoutPriorityDefaultHigh 不会编译。 编辑了我的答案。实际上优先级 999 或 990 都适合你。这些优先级几乎与 1000 要求的优先级一样高,因此它们不会轻易受到影响。 当我设置这个时我的应用程序崩溃:( 如果你这样做,那么你的约束将不会被考虑在内,因为它的优先级将低于自动生成的。即使作者告诉它有效,但它对我不起作用——我无法解释为什么它对他有效……【参考方案2】:

此警告在 ios 13 中仍然存在问题。

之所以出现是因为键盘扩展的视图(KeyboardViewControllerview 属性)将自动调整掩码转换为约束。

你想要的是通过调用移除自动生成的高度约束:

view.translatesAutoresizingMaskIntoConstraints = false

然而,这还不够:您必须替换重要的生成约束。

我在viewWillAppear 函数中这样做了,因为此时父视图存在。我使用constraintHaveBeenAdded 属性来避免多次添加相同的约束,因为该函数可以重复调用。

class KeyboardViewController: UIInputViewController 

  private var constraintsHaveBeenAdded = false

  override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)
    initKeyboardConstraints()
  

  private func initKeyboardConstraints() 
    if constraintsHaveBeenAdded  return 
    guard let superview = view.superview else  return 
    view.translatesAutoresizingMaskIntoConstraints = false
    view.leftAnchor.constraint(equalTo: superview.leftAnchor).isActive = true
    view.bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true
    view.rightAnchor.constraint(equalTo: superview.rightAnchor).isActive = true
    view.heightAnchor.constraint(equalToConstant: 250.0).isActive = true
    constraintsHaveBeenAdded = true
  


您甚至可以移除高度约束,让子视图约束决定键盘高度。

【讨论】:

以上是关于iOS 8 自定义键盘:更改高度而不发出警告“无法同时满足约束...”的主要内容,如果未能解决你的问题,请参考以下文章

如何更改iOS自定义键盘的高度?

iOS 8自定义键盘的高度限制根本不起作用

iOS 8 自定义键盘自动布局键

iOS 8 自定义键盘方向更改

播放声音的 iOS 8 自定义键盘

设备上的 iOS 8 自定义键盘