当前位置:  开发笔记 > 运维 > 正文

keyboardWillShow被调用其他应用程序的键盘

如何解决《keyboardWillShow被调用其他应用程序的键盘》经验,为你挑选了2个好方法。

我知道这是应该发生的事情,但它导致了我不知道如何修复的问题.

我想在键盘显示时向上移动我的视图,以便我的文本字段保持可见.

我的文本字段有数字键盘.

我使用通知并keyboardWillShow/Hide在选择文本字段时向上/向下移动视图.

现在假设我点击一个文本字段,然后切换到另一个使用不同键盘(而不是数字键盘)的应用程序.keyboardWillShow用错误键盘的大小调用(来自另一个应用程序的键盘)并且我的视图移动的数量错误(它根本不应该移动).因此,当我回到我的应用程序时,我的视图位于错误的位置,键盘甚至没有显示,然后keyboardWillHide被调用,视图被移回原位(无处不在).但首先keyboardWillShow不应该为其他应用程序调用它.

我正在删除通知viewWillDisappear,但这仍然发生...也许keyboardWillShow是在viewWillDisappear为我的之前调用其他应用程序?

这是我的代码:

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
        })
    }
}

编辑:正如@JasonNam在他的回答中指出的那样,在切换应用程序时不会调用viewWillDisappear,所以我不得不添加一个applicationWillResignActive通知来删除键盘通知以及applicationDidBecomeActive添加它们的通知.


编辑2:@ sahara108的解决方案似乎更清晰,我看不出任何缺点.我只需要UIApplication.sharedApplication().applicationState == .Active在使用keyboardWillShow做任何事情之前检查一下.



1> sahara108..:

我建议你检查你的方法是否textField是第一响应者keyboardWillShown.如果不是,则忽略该通知.

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

更新: 如果您检查,它将更安全,而不是检查firstResponderUIApplication.shareApplication().applicationSate == .Active



2> Oleksii Nezh..:

仅限iOS 9+:

来自键盘的NSNotification包含以下内容:

UIKeyboardIsLocalUserInfoKey -NSNumber对象的键,该对象包含一个布尔值,该布尔值标识键盘是否属于当前应用程序。

就我而言,我也这样做(OP可能也需要这样做):

func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
    return UIApplication.shared.applicationState == .active
}

这样,在应用程序之间切换时键盘不会隐藏。

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有