Rasto
Rasto

Reputation: 17774

iOS 8 Custom Keyboard: Changing the height without warning 'Unable to simultaneously satisfy constraints...'

There are several SO answers about how to change Custom Keyboard height. Some of them work for example here but those that work lead to constrains conflict error printed to console output:

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

Here is my very simple keyboard controller that sets custom keyboard height (is 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)
    }
}

This produces the annoying output error that my constrain heightConstraint that I added in updateViewConstraints is in conflict with constrain identified as UIView-Encapsulated-Layout-Height.

I tried to remove conflicting constant (UIView-Encapsulated-Layout-Height) in updateViewConstraints as follows:

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

This did not help, the output warning is still there. How do I solve this? Specifically, what can I do to get rid of the output error message?

Upvotes: 3

Views: 1872

Answers (2)

Steve G.
Steve G.

Reputation: 688

This warning is still a problem in iOS 13.

It appears because the view of the keyboard extension (KeyboardViewController’s view property) translates autoresizing mask into constraints.

What you want is removing the automatically generated height constraint by calling:

view.translatesAutoresizingMaskIntoConstraints = false

Nevertheless, this is not enough: you have to replace the important generated constraints.

I did that in the viewWillAppear function, as the parent view exists at this moment. I use the constraintHaveBeenAdded property to avoid to add several times the same constraints, as the function can be called repeatedly.

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
  }

}

You can even remove the height constraint and let the subviews constraint decide of the keyboard height.

Upvotes: 2

Ezimet
Ezimet

Reputation: 5078

Try setting heightConstraint priority to less than 1000. Some thing like blow :

heightConstraint.priority = 990

OR

heightConstraint.priority = 999

Upvotes: 3

Related Questions