キーボードの表示・非表示でViewの変更などをする際に、ViewControllerごとにaddObserverやremoveObserverを書いたりするのをなんとか減らしたいと思い、下記のような実装をしてみました。
protocol KeyboardObservable: class {
var keyboardObservers: [Any] { get set }
func keyboardWillShow(_ notification: Notification)
func keyboardDidShow(_ notification: Notification)
func keyboardWillHide(_ notification: Notification)
func keyboardDidHide(_ notification: Notification)
func addKeyboardObservers()
func removeKeyboardObservers()
}
extension KeyboardObservable {
func addKeyboardObservers() {
keyboardObservers = [
(.UIKeyboardWillShow, keyboardWillShow(_:)),
(.UIKeyboardDidShow, keyboardDidShow(_:)),
(.UIKeyboardWillHide, keyboardWillHide(_:)),
(.UIKeyboardDidHide, keyboardDidHide(_:))
].map { NotificationCenter.default.addObserver(forName: $0, object: nil, queue: .main, using: $1) }
}
func removeKeyboardObservers() {
keyboardObservers.forEach { NotificationCenter.default.removeObserver($0) }
keyboardObservers.removeAll()
}
}
keyboardWillShow(_:)
keyboardDidShow(_:)
keyboardWillHide(_:)
keyboardDidHide(_:)
はprotocolによって実装が強制されるので、タイポなどによってactionが呼ばれないというミスが減ります。
class ViewController: UIViewController, KeyboardObservable {
var keyboardObservers: [Any] = []
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
addKeyboardObservers()
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
removeKeyboardObservers()
}
func keyboardWillShow(_ notification: Notification) {
//キーボードが表示される前の処理
}
func keyboardDidShow(_ notification: Notification) {
//キーボードが表示された後の処理
}
func keyboardWillHide(_ notification: Notification) {
//キーボードが非表示にされる前の処理
}
func keyboardDidHide(_ notification: Notification) {
//キーボードが非表示にされた後の処理
}
}
上記のようにKeyboardObservableを採用することで、キーボードのNotificationをハンドリングしたいViewControllerだけで呼び出しが可能になります。