UIKeyboardWillShow通知在物理设备上调用了两次,但在模拟器中未调用

时间:2018-08-08 21:01:51

标签: ios swift xcode

当键盘被调用时,我正在将UIView向上移动,在模拟器中可以正常工作,但是无论出于什么原因,我两次在UIKeyboardWillShow通知中调用实际代码时,我都会在实际设备上运行代码。我没有使用任何自定义键盘。

在viewDidLoad方法中,我称为此方法。

func registerKeyBoardNotifications(){
    NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillAppear(notification:)), name: .UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: .UIKeyboardWillHide, object: nil)
}

然后在viewWillDisappear中删除这些观察者。

@objc func keyBoardWillAppear(notification: NSNotification){
    if let userInfo = notification.userInfo,
       let endFrame = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue,
       let beginFrame = userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue,
       beginFrame.isEqual(to: endFrame) == false{
          let keyboardSize = endFrame.cgRectValue
          self.view.frame.origin.y -= keyboardSize.height - keyboardConstant
          signUpButton.isEnabled = false
    }
}

keyboardWillAppear处理程序在物理设备上被调用两次,但在模拟器中被调用一次,在最近的两天里试图弄清楚这一点。

Xcode 9.4.1迅捷4.1

3 个答案:

答案 0 :(得分:1)

这可能发生,并且没有任何文档可以保证仅一个通知。

因此,您应该只在代码中处理它,而不每次都减去键盘高度。一个更聪明的解决方案是根据键盘的末端框架来计算您的视框。

答案 1 :(得分:0)

正确的方法是,问自己正确的问题。例如,以前是不是键盘没有覆盖我的视野,现在是?那是应该被视为“进入”的场合。

我有一个实用程序功能,可根据通知的userInfo字典和我们关注的视图范围来计算几何形状。如果键盘不在视图的范围之内,而现在已经在视图的范围之内,则说明它正在进入;如果它在视图的范围之内,但现在不在范围之内,则它正在退出。我们返回该信息,以及视图边界坐标中的键盘框架:

enum KeyboardState {
    case unknown
    case entering
    case exiting
}
func keyboardState(for d:[AnyHashable:Any], in v:UIView?) 
    -> (KeyboardState, CGRect?) {
        var rold = d[UIResponder.keyboardFrameBeginUserInfoKey] as! CGRect
        var rnew = d[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
        var ks : KeyboardState = .unknown
        var newRect : CGRect? = nil
        if let v = v {
            let co = UIScreen.main.coordinateSpace
            rold = co.convert(rold, to:v)
            rnew = co.convert(rnew, to:v)
            newRect = rnew
            if !rold.intersects(v.bounds) && rnew.intersects(v.bounds) {
                ks = .entering
            } 
            if rold.intersects(v.bounds) && !rnew.intersects(v.bounds) {
                ks = .exiting
            }
        }
        return (ks, newRect)
}

当键盘显示时,我们检查它是否正在输入,并做出相应的响应:

@objc func keyboardShow(_ n:Notification) {
    let d = n.userInfo!
    let (state, rnew) = keyboardState(for:d, in:myView)
    if state == .entering {
        // ...
    }
}

答案 2 :(得分:0)

我似乎已经弄清楚了为什么UIkeyboardWillShow Notification通知在物理设备而不是模拟器上触发两次。设置某些“文本输入”特征时,它与键盘上方的键盘建议有关。任何在键盘上方引起建议的文本输入特征都会导致该通知触发两次,而不是一次,我猜测是一次针对键盘本身,另一次针对键盘上方的建议栏。 (在我的情况下,因为在模拟器上没有建议,所以它在模拟器中触发了一次,但在设备上触发了两次,因为在真实设备上有建议)。这是一个奇怪的案例,似乎没有记录在案。

一种解决方法(我选择的途径)是通过将所有“文本输入”特征设置为默认值并将文本字段的内容类型设置为“用户名”来禁用所有建议。

enter image description here

另一种解决方案是在调整您尝试移动的UIView的框架之前,先考虑代码中的第二个UIkeyboardWillShowNotifcation通知。