1

To assure that textfields in a tabular view are always visible with a keyboard enabled, I want to shift the tableview upwards in case it would cover the controls. I have problems to do this in combination with autolayout applied programmatically.

The constraints for the tableview are defined as follows:

override func viewWillLayoutSubviews() {
    let views = ["tableView": tableView]

    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[tableView]|", options: NSLayoutFormatOptions(rawValue: 0), metrics: nil, views: views))

    let topConstraint = NSLayoutConstraint(item: tableView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
    self.view.addConstraint(topConstraint)

    bottomConstraint = NSLayoutConstraint(item: tableView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
    self.view.addConstraint(bottomConstraint)
}

To detect the keyboard via NSNotificationCenter the following methods are called (based on an answer at Getting keyboard size from userInfo in Swift):

func keyboardWillHide(sender: NSNotification) {
            bottomConstraint.constant = 0.0
            UIView.animateWithDuration(0.2, animations: { () -> Void in self.view.layoutIfNeeded() })
     }

And

func keyboardWillShow(sender: NSNotification) {
    if let userInfo = sender.userInfo {
        if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue().size.height {
            self.view.layoutIfNeeded()

            bottomConstraint.constant = keyboardHeight
            UIView.animateWithDuration(0.2, animations: { () -> Void in
                self.view.layoutIfNeeded()
            })
        }
    }
}

However, with this the code the constraints are not updated correctly. Instead, the following error appears:

Unable to simultaneously satisfy constraints.
…
(
    "<NSLayoutConstraint:0x109941b50 UITableView:0x1028ea600.bottom == UIView:0x10993b930.bottom>",
    "<NSLayoutConstraint:0x102417290 UITableView:0x1028ea600.bottom ==     UIView:0x10993b930.bottom + 271>"
)

Why are the constraints not updated? Is viewWillLayoutSubviews the correct location for these constraints?

Community
  • 1
  • 1
Gerard
  • 349
  • 2
  • 16
  • Try removing `topConstraint ` from code. I guess it gives constraints warning. – Kampai May 27 '16 at 13:26
  • The topConstraint is unrelated to the bottomConstraint. The warnings only appear when I try to update bottomConstraint. – Gerard May 28 '16 at 13:48

1 Answers1

3

If you set constraints from interface builder then you can take outlet of any constraint by just ctrl + dragging. and then you can manage it's constant when keyboard appear and hides.

If you add constraint programmatically then you can set identifier of it and by that identifier you can use that constraint anywhere and can manage constant when keyboard is appear or disappear.

And if you don't want to manage all this stuff then you can use great third party library IQKeyboardmanager.

Just drag and drop it to your project thats it!! You not need to do anything, everything will manage automatically.

Hope this will help :)

Ketan Parmar
  • 27,092
  • 9
  • 50
  • 75
  • All constraints are defined programmatically and directly accessible (i.e. the relevant constraint 'bottomConstraint' can directly be managed without an identifier). Although the library is a good suggestion (and surely of help), my main problem is that I do not succeed to update a constraint after a view is initialized (it appears that a new one is added instead of updated, which results in a conflict). I encounter this problem not only in this specific situation with a keyboard appearance, so I would be happy to get this issue solved. – Gerard May 28 '16 at 13:50