keyboardWillShow é chamado para teclados de outros aplicativos

Sei que é o que deveria acontecer, mas está me causando problemas que não sei como consertar.

Quero mover minha visualização para cima quando o teclado aparecer, para que meus campos de texto permaneçam visíveis.

Meus campos de texto têm teclados numéricos.

Eu uso notificações ekeyboardWillShow/Hide para mover minha visão para cima / baixo quando um campo de texto é selecionado.

Agora, suponha que eu toque em um campo de texto e depois mude para outro aplicativo que esteja usando um teclado diferente (não o teclado numérico).keyboardWillShow é chamado com o tamanho do teclado errado (o do outro aplicativo) e minha visualização é movida para a quantidade errada (nem deve ser movida). Então, quando eu volto para o meu aplicativo, minha visualização está no lugar errado e o teclado nem aparece, e entãokeyboardWillHide é chamado e a exibição é movida de volta ao lugar (do nada). MaskeyboardWillShow nem sequer deve ser chamado para o outro aplicativo em primeiro lugar.

Estou removendo as notificações emviewWillDisappear, mas isso ainda acontece ... talvezkeyboardWillShow é chamado para os outros aplicativos antesviewWillDisappear é chamado para o meu?

Aqui está o meu código:

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
    for subview in self.view.subviews {
        if subview.isKindOfClass(UITextField) {
            let textField = subview as! UITextField
            textField.addTarget(self, action: "textFieldDidReturn:", forControlEvents: UIControlEvents.EditingDidEndOnExit)
            textField.addTarget(self, action: "textFieldDidBeginEditing:", forControlEvents: UIControlEvents.EditingDidBegin)
        }
    }
}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    NSNotificationCenter.defaultCenter().removeObserver(self)
}

func keyboardWillShow(notification: NSNotification) {
    self.keyboardIsShowing = true
    if let info = notification.userInfo {
       self.keyboardFrame = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
       self.arrangeViewOffsetFromKeyboard()
    }
}

func keyboardWillHide(notification: NSNotification) {
    self.keyboardIsShowing = false
    self.returnViewToInitialFrame()
}

func arrangeViewOffsetFromKeyboard() {
    if let textField = activeTextField {
        let theApp: UIApplication = UIApplication.sharedApplication()
        let windowView: UIView? = theApp.delegate!.window!
        let textFieldLowerPoint = CGPoint(x: textField.frame.origin.x, y: textField.frame.origin.y + textField.frame.size.height)
        let convertedTextFieldLowerPoint = textField.superview!.convertPoint(textFieldLowerPoint, toView: windowView)
        let targetTextFieldLowerPoint = CGPoint(x: textField.frame.origin.x, y: self.keyboardFrame.origin.y)
        let targetPointOffset = targetTextFieldLowerPoint.y - convertedTextFieldLowerPoint.y
        let adjustedViewFrameCenter = CGPoint(x: self.view.center.x, y: self.view.center.y + targetPointOffset)
        print(targetPointOffset) // When I change to a different app this prints the wrong value… but none of this should even get called.
        if targetPointOffset < 0 {
            UIView.animateWithDuration(0.3, animations: {
                self.view.center = adjustedViewFrameCenter
            })
        }
    }
}

func returnViewToInitialFrame() {
    let initialViewRect = CGRect(x: 0.0, y: 0.0, width: self.view.frame.size.width, height: self.view.frame.size.height)
    if !CGRectEqualToRect(initialViewRect, self.view.frame) {
        UIView.animateWithDuration(0.2, animations: {
            self.view.frame = initialViewRect
        })
    }
}

Edit: Como o @JasonNam apontou em sua resposta, o viewWillDisappear não é chamado ao alternar entre aplicativos, então tive que adicionar umapplicationWillResignActive notificação para remover as notificações do teclado e umapplicationDidBecomeActive notificação para adicioná-los de volta.

Edit 2: a solução do @ sahara108 parece mais limpa e não vejo nenhuma desvantagem. Eu só tinha que procurarUIApplication.sharedApplication().applicationState == .Active antes de fazer qualquer coisa no keyboardWillShow.

questionAnswers(6)

yourAnswerToTheQuestion