UIResponder.keyboardDidShowNotification が他のアプリに切替した時にも通知される問題
iOS アプリでキーボードが表示されたイベントを知りたい時に UIResponder.keyboardDidShowNotification
を通知を受ける。
コードは以下のたとえば下のようになる。
import UIKit import os class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let textField = UITextField(frame: CGRect(x: 0, y: 0, width: 150, height: 34)) textField.center = self.view.center textField.borderStyle = .roundedRect self.view.addSubview(textField) NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow), name: UIResponder.keyboardDidShowNotification, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { self.view.endEditing(true) } @objc private func keyboardDidShow(notification: NSNotification) { // キーボードが表示になった時の通知 } @objc private func keyboardWillHide(notification: NSNotification) { // キーボードが非表示になった時の通知 }
ただ、これだと「キーボードを開いている他のアプリ」に切替した時も、キーボード表示の通知がきてしまう。
例えば、以下のようにキーボードを開いている状態の Safari を開いた時などだ。
このような問題があるので、どうやって自分のアプリ/他のアプリのキーボード通知を見分けるのか調べると、以下のドキュメントがあった。
https://developer.apple.com/documentation/uikit/uiresponder/1621603-keyboardislocaluserinfokey
keyboardIsLocalUserInfoKey
The key for an NSNumber object containing a Boolean that identifies whether the keyboard belongs to the current app. With multitasking on iPad, all visible apps are notified when the keyboard appears and disappears. The value of this key is true for the app that caused the keyboard to appear and false for any other apps.
つまり UIResponder.keyboardIsLocalUserInfoKey
の値が true なら自分のアプリ、false なら他のアプリ、ということになる。
実際に下のようなコードで試すと、期待する結果が得られた。
@objc private func keyboardDidShow(notification: NSNotification) { guard let isLocalUserInfoKey = notification.userInfo?[UIResponder.keyboardIsLocalUserInfoKey] as? NSNumber else { return } print("keyboardDidShow ", separator: "", terminator: "") if isLocalUserInfoKey.boolValue { print("-> My app event") } else { print("-> Other app event") } }