2

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.

iWheelBuy
  • 5,470
  • 2
  • 37
  • 71

2 Answers2

2

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

iWheelBuy
  • 5,470
  • 2
  • 37
  • 71
Neil Galiaskarov
  • 5,015
  • 2
  • 27
  • 46
  • Indeed, I downloaded your project and it does not work. Please check my updated answer which works with your project. – Neil Galiaskarov Dec 19 '17 at 08:37
  • There is one little thing which should also be mentioned in your answer. 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 – iWheelBuy Dec 19 '17 at 09:12
2

The problem happens because responders are managed (restored, saved) by UIKit between viewWillAppear and viewDidAppear, just before view has appeared, and between viewWillDisapear: and viewDidDisapear:, just before view has disappeared. That is why any change made to responders is visible during animation.

Instead of removing responders, to get the effect you want, you can prevent views from becoming responders before view appears again.

The simplest way to do this for UITextField and UITextView is to temporary disable interaction just before view will appear, and then restore it after the view did reappeared.

override func viewWillAppear(_ animated: Bool) {
    self.viewTextField.isUserInteractionEnabled = false
    self.viewTextView.isUserInteractionEnabled = false
    super.viewWillAppear(animated)
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.viewTextField.isUserInteractionEnabled = true
    self.viewTextView.isUserInteractionEnabled = true
}

This will give you the same effect Telegram has.

XeNoN
  • 694
  • 6
  • 16
  • This trick works with UITextField, but it doesn't work with UITextView... And there are only UITextViews in my project... ): – iWheelBuy Dec 19 '17 at 01:33