UIWindow上的偏移使选项卡栏向后滑动时显示两次

时间:2019-02-22 16:52:11

标签: ios swift

在发送keyboardWillShowNotification时,可以通过向上移动系统键盘的窗口来将系统键盘移动到选项卡栏上方。但是,当视图控制器嵌入在导航控制器中并且我缓慢地向后滑动时,选项卡栏会出现两次。如果取消了滑动操作,则偏移量也会重置为正常值(显然是因为未触发kyeboardWillShow事件)。观察keyboardWillChangeFrame也不适用。

enter image description here

这里有一些示例代码可以准确显示我在做什么:

import UIKit
import Foundation

class ViewController: UIViewController { }

class SecondViewController: UIViewController {

    let textField = UITextField(frame: CGRect(x: 150, y: 150, width: 150, height: 150))

    override func viewDidLoad() {
        super.viewDidLoad()
        textField.keyboardType = .decimalPad
        view.addSubview(textField)

        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        textField.becomeFirstResponder()
    }
}

extension SecondViewController {
    private var keyboardOffset: CGFloat {
        return -tabBarHeight
    }

    private var tabBarHeight: CGFloat {
        return tabBarController?.tabBar.frame.height ?? 0
    }

    private var keyboardWindowPredicate: (UIWindow) -> Bool {
        return { $0.windowLevel > UIWindow.Level.normal }
    }

    private var keyboardWindow: UIWindow? {
        return UIApplication.shared.windows.last(where: keyboardWindowPredicate)
    }

    @objc private func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue, let keyboardWindow = keyboardWindow {
            keyboardWindow.frame.origin.y = keyboardOffset

        }
    }

    @objc private func keyboardWillHide(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue, let keyboardWindow = keyboardWindow {
            keyboardWindow.frame.origin.y = 0
        }
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        textField.resignFirstResponder()
    }
}

extension Sequence {
    func last(where predicate: (Element) throws -> Bool) rethrows -> Element? {
        return try reversed().first(where: predicate)
    }
}

谁能解释为什么会发生这种情况,我该怎么做才能防止这种情况发生?我知道在iOS中移动键盘不是常见的事情,但这不是我的决定,我正在尝试使用它。

1 个答案:

答案 0 :(得分:0)

也许的原因如下:

docstouchesBegan(_:with:)说:

  

在视图或页面中检测到新触摸时,UIKit会调用此方法。   窗口。许多UIKit类重写此方法并使用它来处理   相应的触摸事件。这个的默认实现   方法将消息转发到响应者链。创建您的   自己的子类,请调用super来转发您没有的任何事件   处理自己。例如,[super touchesBegan:touches   withEvent:event];如果您在不调用super(a   常用模式),您还必须覆盖其他方法   处理触摸事件,即使您的实现什么也不做。

因此,我要做的第一件事是按照文档要求

进行覆盖
  

其他处理触摸请求的方法,即使您的   实现什么都不做