Edited at

iOS11でkeyboardの高さを正しく取得する

More than 1 year has passed since last update.


問題

よくScrollView+TextFieldのような画面で、キーボードが隠れないようにするためにキーボードの開閉の通知を受け取ってscrollInsetをいい感じに調整したりする場合があります

    override func viewDidLoad() {

super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: .UIKeyboardWillShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: .UIKeyboardWillHide, object: nil)
}

@objc private func keyboardWillShow(_ notification: Notification) {
guard let userInfo = notification.userInfo as? [String: Any] else {
return
}
guard let keyboardInfo = userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue else {
return
}
guard let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? Double else {
return
}
let keyboardSize = keyboardInfo.cgRectValue.size
let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0) //←
UIView.animate(withDuration: duration, animations: {
self.scrollView.contentInset = contentInsets
self.scrollView.scrollIndicatorInsets = contentInsets
self.view.layoutIfNeeded()
})
}

@objc private func keyboardWillHide(_ notification: Notification) {
scrollView.contentInset = .zero
scrollView.scrollIndicatorInsets = .zero
}

しかし、iOS11だと上記処理のうち、 keyboardSize.height が0になってしまう問題があるようです。

これにハマって、最初の1回目のキーボード表示では高さが取得できていい感じにinsetが調整されるものの、2回目以降、アプリを再起動するまでずっと0になってて... :innocent:


修正方法

UIKeyboardFrameBeginUserInfoKeyUIKeyboardFrameEndUserInfoKey に変更します。

guard let keyboardInfo = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue else {

return
}

いままでBeginとEndとあってどっち使うんだって思っていたんですけど、Endの方を使っておけば大丈夫そうです。


参考