Por que o observador onKeyboardDisplayed é chamado antes de textViewDidBeginEditing

Dec 23 2020

Meu aplicativo está em alta. Quando edito um UITextField, às vezes o teclado oculta o campo. Portanto, uso o delegado textFieldDidBeginEditing para definir um "activeTextField" (e textFieldDidEndEditing para redefini-lo como nulo). Em seguida, em viewDidLoad, adiciono um observador vinculado a uma função onKeyboardDisplayed onde testo o valor de "activeTextField" para poder deslizar a tela para cima, se necessário. E funciona bem :)

A má notícia é que tentei fazer o mesmo para um UITextView, usando o delegado textViewDidBeginEditing para definir um "activeTextView". Mas, ao contrário de UITextField, o delegado é chamado depois de onKeyboardDisplayed, de forma que o teclado ainda oculta meu 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)
        }
    }
}

Você conhece uma maneira de consertar isso?

Respostas

2 syntiz Dec 23 2020 at 20:36

Finalmente encontrei uma solução aqui: eventos de teclado chamados antes dos eventos de delegado UITextView

Eu mudei keyboardWillShowNotification

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)

E agora funciona bem: minha função onKeyboardDisplayed é chamada após o delegado textViewDidBeginEditing

1 LucaSfragara Dec 23 2020 at 18:54

A maneira padrão de lidar com a aparência do teclado é esta

Em seu 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
}

Isso move o quadro de exibição para cima e para baixo de acordo com a altura do teclado. Se entendi sua pergunta corretamente, acredito que isso pode ajudá-lo