1

I will try to be as quick as I can. I have a Main view with a container with a height of 0 and whenever the keyboard is enabled I set the container to be the same height of the keyboard and I have a a button and a email field and I have set constraints to this container, basically pushing the elements up. I have set the keyboard to be enabled when the view is loaded and its working normal with he main view but as soon as I press the button to go to the next view, the keyboard opens but the buttons and the email field stay behind the keyboard because the constraints are not working, but when I press the home button and close the app (not from the background) and re open it, the constraints work normally. This only happens when I embed a navigation controller to the main view, otherwise its perfectly working. Any ideas?

I have the exact same code on both Views. Ps: Sorry for the long post, I had no idea how to explain it.

@IBOutlet weak var emailTF: UITextField!

@IBOutlet weak var bottomHeight: NSLayoutConstraint!`

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

    NotificationCenter.default.addObserver(
        self,
        selector: #selector(keyboardWillShow),
        name: NSNotification.Name.UIKeyboardWillShow,
        object: nil
    )

    // Show keyboard by default
    emailTF.becomeFirstResponder()
}

@objc func keyboardWillShow(_ notification: Notification)
{
       if let userInfo = notification.userInfo
    {
        if let keyboardSize = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        {
            bottomHeight.constant = keyboardSize.height
            view.setNeedsLayout()
        }
    }
}

Update: I found part of the problem. When loading the second view I wasn't able to get the keyboard height, I changed the second view code from "viewWillAppear" to "viewDidAppear", making the container the same as the keyboard height, BUT there is another issue. When I load the first view I get the keyboard height of 271 (which is correct), when I move to the second view the keyboard height is 226 for some reason, making the textField to move 45. The same thing happens when I press the back button to go back from the secondView to the first, the keyboard height is 226. When I press the home button and reopen the app it doesn't matter which screen I am I get the keyboard height of 271, which is the correct height. What I am doing wrong?

Update 2: SOLVED!

Because my code was only working without the navigation controller I had a feeling that it was something with the quick animation and transition the navigation controller had and it was preventing the code to be read before loading, so I tried to write this line of code emailTF.resignFirstResponder() to my button action and it worked! So basically I had to dismiss the keyboard before loading it up in the next view. I hope I helped some users having the same issue.

2 Answers2

0

first ensure that the VC containing the view that is being changed is the delegate of the textfield/textview then call .becomeFirstResponder() from viewWillAppear. Make sure you are registering/deregistering keyboard notifications properly. If at all possible, you can use a scroll view (over the default UIView) to contain the ViewControllers subviews instead of altering constraints.

func registerForKeyboardNotifications(){
    //Adding notifies on keyboard appearing
    NotificationCenter.default.addObserver(forName: Notification.Name.UIKeyboardWillShow, object: nil, queue: nil, using: keyboardWasShown)
    NotificationCenter.default.addObserver(forName: Notification.Name.UIKeyboardWillHide, object: nil, queue: nil, using: keyboardWillBeHidden)
}

func deregisterFromKeyboardNotifications(){
    //Removing notifies on keyboard appearing
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardDidShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: Notification.Name.UIKeyboardWillHide, object: nil)
}

func keyboardWasShown(notification: Notification) -> Void {
    //Need to calculate keyboard exact size due to Apple suggestions
    self.scrollView.isScrollEnabled = true
    var info = notification.userInfo!
    var keyboardSize:CGRect = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
    if keyboardSize.size.height <= 0 { // to fix bug on iOS 11
        keyboardSize = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
    }
    self.scrollView.contentInset.bottom = keyboardSize.height //add this much
    self.scrollView.scrollIndicatorInsets.bottom = keyboardSize.height //scroll too it.

    var aRect : CGRect = self.view.frame
    aRect.size.height -= keyboardSize.height
    if let activeField = self.activeTextView {
        if (!aRect.contains(activeField.frame.origin)){
            self.scrollView.scrollRectToVisible(activeField.frame, animated: true)
        }
    }
}

func keyboardWillBeHidden(notification: Notification){
    self.scrollView.contentInset.bottom = 0
    self.scrollView.isScrollEnabled = true
    self.scrollView.alwaysBounceVertical = true
}
RLoniello
  • 2,309
  • 2
  • 19
  • 26
  • I already found the issue and updated the post. You mentioned scrollView but in my case that would work because I wanted to move up just one element and using a scrollView would complicate things. Thanks for trying to help! – Alexandre D'Acol Dec 03 '17 at 11:50
  • @AlexandreD'Acol I've always felt it was easier to replace the view with a scroll view and add the reusable code above. Good to hear you fixed it! take care and good luck with your project! – RLoniello Dec 04 '17 at 01:23
  • Good to know about it, I have never used this method but I will definitely try. Thanks ! – Alexandre D'Acol Dec 04 '17 at 12:44
0

Use this line of code self.view.layoutIfNeeded() instead of view.setNeedsLayout()

And make sure about the height of keyboard that you are getting correct height or not.

Thanks!

nitin.agam
  • 1,949
  • 1
  • 17
  • 24
  • Thanks but it’s not working, I changed the line of code and nothing. Also the height of the keyboard is right because when I remove the navigation controller from the views, it works well. Also when I remove the navigation controller and uncheck the “animate” box from the segue , it doesn’t work either. Looks like something is preventing the constraints to load and when there’s some animation it allow the constraints to work properly. – Alexandre D'Acol Dec 02 '17 at 18:44
  • I did it just for testing, as I said before, the code isn’t working with the navigation controller . – Alexandre D'Acol Dec 02 '17 at 19:13
  • The thing that I don’t understand is that, how come it works perfectly without the navigation controller? That’s weird. – Alexandre D'Acol Dec 02 '17 at 19:27
  • Could you please share the complete code? So that I can run and fix it. – nitin.agam Dec 02 '17 at 20:14
  • I just tested and saw that the function `@objc func keyboardWillShow(_ notification: Notification)` isn't being called on the second view, preventing the container to have the same height of the keyboard. Any thoughts ? – Alexandre D'Acol Dec 03 '17 at 06:26