絶対忘れる自信があるので書いておきます。
なんとなく、この辺りのインターフェースもまた変わりそうな予感がするので、暫定Swift 5、iOS 13版です。
NotificationCenter(raw)
NotificationCenter
はライフサイクルに合わせてobserverを破棄してくれるので、addObserver
の最初の引数で適切なオブジェクトを指定してあげれば、明示的にremoveObserver
を呼ぶ必要はないです。
NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillChangeFrame(_:)), name: UIResponder.keyboardWillChangeFrameNotification, object: nil )
Text Fieldをキーボードに追従させて動かす例。
相変わらずI/Fがイケてないので、いったん値を探してNSValue
にキャストする必要があります。
@objc private func keyboardWillChangeFrame(_ notification: Notification) { guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return } let keyboardHeight = UIScreen.main.bounds.height - keyboardFrame.cgRectValue.minY textField.transform = CGAffineTransform(translationX: 0, y: min(0, -keyboardHeight + view.safeAreaInsets.bottom)) }
実際に使う場合はSafe Areaの分を考慮する必要があるので、上のコードのような調整をする必要があります。
CGAffineTransform
や、layoutIfNeeded()
を使えばいい感じのアニメーションになりますが、値は細かくは飛んでこないので、その他の方法を使う場合は、keyboardAnimationDurationUserInfoKey
なども活用します。
RxSwift
NotificationCenter
にRxが生えてるのでそれを利用します。
let keyboardHeight: Observable<CGFloat> = NotificationCenter.default.rx.notification(UIResponder.keyboardWillChangeFrameNotification) .compactMap { notification -> CGFloat? in guard let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return nil } return UIScreen.main.bounds.height - keyboardFrame.cgRectValue.minY }