Search code examples
iosuiviewuiviewcontrollerfirst-responderuiresponder

Keyboard does not disappear after viewDidDisappear


iOS 11.2, Xcode 9.2

I've tried all the ways to dismiss keyboard on viewDidDisappear of the old UIViewController AFTER a new UIViewController is pushed into UINavigationController stack. But with no luck.

If I dismiss it on viewWillDisappear - it will be dismissed but with animation DURING push animation. It is not the desired behaviour. I want the old UIViewController's keyboard to be dismissed only when the controller is no longer visible.

The behavior should be like in Telegram app:

In any dialog with visible keyboard press on opponents avatar and you'll be pushed to opponents account information. Then, if you press back button, you'll be redirected back to a dialog. But the keyboard will be already dismissed.

Any help is appreciated!

P.S. The question might look like a duplicate, but I have failed to make it work with the solutions I found.

Edit 1.

I have created a small TEST PROJECT which represents a failure to achieve the desired behavior.

In order to reproduce the undesired behavior:

  • Launch the app.
  • Tap on UITextField or UITextView and wait for the keyboard to appear.
  • Tap on "Next" button and wait for a new controller to be pushed.
  • Tap on "Back" button and wait for a new controller to be popped.

As a result - the initial view controller will have the active keyboard after the push/pop actions. I need the keyboard to be hidden after the push/pop actions. Also, the keyboard should not be dismissed before the initial view controller becomes invisible, it should be dismissed after viewDidDisappear action.


Solution

  • There are cases where no text field is the first responder but the keyboard is on screen. In these cases, the above methods fail to dismiss the keyboard.

    Use the property: isEditable of your textView. Here is a tested code:

      override func viewWillAppear(_ animated: Bool) {
        self.viewTextView.isEditable = false
        super.viewWillAppear(animated)
      }
    
      override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.viewTextView.isEditable = true
      }
    

    Results:

    enter image description here

    Comments from @iWheelBuy:

    Sometimes, text views will have inputAccessoryView. The way you do it will make the keyboard disappear, but the inputAccessoryView will remain... That is why you should also make inputAccessoryView = nil or inputAccessoryView = UIView() when setting isEditable = false