Por qué se llama al observer onKeyboardDisplayed antes que textViewDidBeginEditing
Mi aplicación es rápida. Cuando edito un UITextField, a veces el teclado oculta el campo. Entonces uso el delegado textFieldDidBeginEditing para establecer un "activeTextField" (y textFieldDidEndEditing para restablecerlo a cero). Luego, en viewDidLoad agrego un observador vinculado a una función onKeyboardDisplayed donde pruebo el valor de "activeTextField" para poder deslizar la pantalla hacia arriba si es necesario. Y funciona bien :)
La mala noticia es que traté de hacer lo mismo para un UITextView, usando delegado textViewDidBeginEditing para establecer un "activeTextView". Pero a diferencia de UITextField, el delegado se llama después de onKeyboardDisplayed, por lo que el teclado aún oculta mi UITextView.
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisplayed(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
@objc func onKeyboardDisplayed(notification: Notification) {
guard let keyboardRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else {
return
}
var visibleRect : CGRect = self.view.frame
visibleRect.size.height -= keyboardRect.height
if (activeTextField != nil) {
// Get y position of active textField bottom.
let textFieldBottomPosition = activeTextField!.convert(CGPoint.zero, to: nil).y + activeTextField!.frame.height
if(textFieldBottomPosition > visibleRect.size.height) {
// swipe up
view.frame.origin.y = (visibleRect.size.height - textFieldBottomPosition - 6)
}
}
if (activeTextView != nil) {
// Get y position of active textView bottom.
let textViewBottomPosition = activeTextView!.convert(CGPoint.zero, to: nil).y + activeTextView!.frame.height
if(textViewBottomPosition > visibleRect.size.height) {
// swipe up
view.frame.origin.y = (visibleRect.size.height - textViewBottomPosition - 6)
}
}
}
¿Conoces una forma de solucionarlo?
Respuestas
Finalmente encontré una solución aquí: eventos de teclado llamados antes de eventos delegados de UITextView
Cambié el teclado WillShowNotification
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisplayed(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
por keyboardDidShowNotification
NotificationCenter.default.addObserver(self, selector: #selector(onKeyboardDisplayed(notification:)), name: UIResponder.keyboardDidShowNotification, object: nil)
Y ahora funciona bien: mi función onKeyboardDisplayed se llama después del delegado textViewDidBeginEditing
La forma estándar de lidiar con la aparición del teclado es esta
En su ViewController:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillShow), name: UIControl.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardWillHide), name: UIControl.keyboardWillHideNotification, object: nil)
}
@objc private func handleKeyboardWillShow(notification: NSNotification){
guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else{
return
}
self.view.frame.origin.y -= keyboardSize.height
}
@objc private func handleKeyboardWillHide(notification: NSNotification){
self.view.frame.origin.y = 0
}
Esto mueve el marco de vista hacia arriba y hacia abajo de acuerdo con la altura del teclado. Si entiendo correctamente su pregunta, creo que esto puede ayudarlo