1

My app monitors changes to the keyboard to animate specific parts of the UI using UIKeyboardWillShow and UIKeyboardWillHide notifications.

The issue I am having is that when I switch from the Messages app with the keyboard shown to my app using the app switcher (in a state where the keyboard is not required), it will trigger the UIKeyboardWillShow notification and then the UIKeyboardWillHide notification which is resulting in my UI jumping up and down a bit.

Is there a way to only listen to keyboard notifications for your own app?

ViewWillAppear

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillChange:", name: UIKeyboardWillChangeFrameNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)

ViewWillDisappear

    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
    NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillChangeFrameNotification, object: nil)
Andrew Varvel
  • 1,286
  • 1
  • 10
  • 19
  • This has nothing to do with what you asked, but you might like to keep in mind that `viewWillAppear` does not necessarily mean that your view will indeed appear (I regard this as annoying or even a massive bug, but it's a fact of life), and `viewWillDisappear` does not necessarily mean that your view will indeed disappear. Thus you would be better off moving these methods to `viewDid`, which means what it says. – matt Sep 21 '15 at 02:21
  • See my answer here http://stackoverflow.com/a/40031687/2774520 – Oleksii Nezhyborets Oct 13 '16 at 21:58

2 Answers2

1

Any code? Do you observe keyboard entire your app or only in a viewcontroller?

Whenever you don't want to listen the changes you can removeObserver

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [[NSNotificationCenter defaultCenter] removeObserver:yourClass name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:yourClass name:UIKeyboardWillHideNotification object:nil];
}

But be careful, you need to use NSNotificationCenter properly.

Luan Nguyen
  • 375
  • 3
  • 6
  • Thanks for your response. I only monitor it in a ViewController. I add the observers in the viewWillAppear (code added above) and have now added remove observer to viewWillDisappear but it is still get keyboard show triggers when you switch back. – Andrew Varvel Sep 21 '15 at 02:13
  • Are you sure that the code in 'viewWillDisappear` will be executed when you leave the app? Try Giving a `NSLog` in `viewWillDisappear` to monitor. – Luan Nguyen Sep 21 '15 at 02:28
0

I came across this problem today. What I ended up doing was adding observers to detect when the app enters and leaves background. If it enters background then remove the keyboard observer else add the keyboard observers. Something like this... I'm sure there's a better way, but this worked for me. Hope this helps.

override func viewDidLoad() {
    super.viewDidLoad()
    registerForPreviewing(with: self, sourceView: collectionView)
    addApplicationStateObservers()
}

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

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    removeKeyboardObservers()
}

deinit {
    removeApplicationStateObservers()
    removeKeyboardObservers()
}

func applicationIsActive() {
    let delay = DispatchTime.now() + 0.1
    DispatchQueue.main.asyncAfter(deadline: delay) {
        self.addKeyboardObservers()
    }
}

// Observers 
// Application state observers were add to handle edge case scenario where if user is playing a video in expanded pip view on iPhone, if user switchs to another app with keyboard then switch back, the video will disppears. Our app removes and re-adds observer as user enter and exit the app. 

func addApplicationStateObservers() {
    NotificationCenter.default.addObserver(self, selector: #selector(applicationIsActive), name: .UIApplicationDidBecomeActive, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(removeKeyboardObservers), name: .UIApplicationDidEnterBackground, object: nil)
}

func removeApplicationStateObservers() {
    NotificationCenter.default.removeObserver(self, name: .UIApplicationDidBecomeActive, object: nil)
    NotificationCenter.default.removeObserver(self, name: .UIApplicationDidEnterBackground, object: nil)
}

func addKeyboardObservers() {
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWasShown), name: .UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden), name: .UIKeyboardWillHide, object: nil)
}

func removeKeyboardObservers() {
    NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil)
    NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
}
Soja
  • 514
  • 6
  • 13