ios - 如何同时获取键盘的大小和选中的 UITextField 的 CGFrame?

标签 ios swift uitextfield uikit nsnotificationcenter

我在运行时动态地使用许多 UITextField 字段填充垂直 UIScrollView 字段。我遇到的问题是键盘会隐藏它会出现的区域中的字段,这可能包括我正在编辑的字段。

我试过了 KeyboardManagement来自苹果文档的解决方案,还尝试了 textFieldDidBeginEditingtextFieldDidEndEditing 上的通知,但两种情况下的问题是 keyboardWillShow 通知有时会先出现,在那种情况下,它不会让我知道正在编辑的是哪个字段。

我在一个实现 UITextFieldDelegate 协议(protocol)的类中有这段代码,这个类的每个对象都持有对这些字段之一的引用并作为它的委托(delegate)工作

func textFieldDidBeginEditing(_ textField: UITextField) {
    self.activeTextfield = self.valueTextField
}

func textFieldDidEndEditing(_ textField: UITextField) {
    self.activeTextfield = nil
}

activeTextfield 变量是对所有这些发生的 UIViewController 中变量的弱引用。在那个 View Controller 中,我有以下代码

class MyClass: UIViewController {
    var activeTextfield: CustomTextField! // This is the variable I was talking about on the previous paragraph

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

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

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        NotificationCenter.default.removeObserver(self)
    }

    @objc func keyboardWillShow(_ notification: Notification) {
        if self.view.frame.origin.y == 0 {
            guard let userInfo = notification.userInfo else { return }
            guard let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }

            let keyboardFrame = keyboardSize.cgRectValue
            let textFieldFrame = activeTextfield!.frame // activeTextfield sometimes is nil because this notification happens before the previous code block

            if textFieldFrame.origin.y + textFieldFrame.size.height > keyboardFrame.origin.y {
                self.view.frame.origin.y -= keyboardFrame.height
            }
        }
    }

    @objc func keyboardWillHide(_ notification: Notification) {
        if self.view.frame.origin.y != 0 {
            guard let userInfo = notification.userInfo else { return }
            guard let keyboardSize = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }

            let keyboardFrame = keyboardSize.cgRectValue

            self.view.frame.origin.y += keyboardFrame.height
        }
    }
}

有什么方法可以强制在键盘通知之前调用 UITextField 委托(delegate)方法?

这是处理这种情况的正确方法吗?

如果没有,我该如何处理?

谢谢

最佳答案

如您的问题所述:

the problem in both cases is that the keyboardWillShow notification comes first sometimes, and in that case it doesn't let me know which field is the one being edited

根据 sequence of events在 apple 的文档中描述,textFieldShouldBeginEditing 是第一个调用的委托(delegate)方法。

所以,你可以

  1. 在委托(delegate)中实现 textFieldShouldBeginEditing 以设置您的事件文本字段,而不是 textFieldDidBeginEditing(确保您从 textFieldShouldBeginEditing 返回 true 以允许编辑)
  2. 使用 keyboardDidShowNotification 而不是 keyboardWillShowNotification

这将确保您在获取键盘框架/详细信息之前标记了您的 UITextField

关于ios - 如何同时获取键盘的大小和选中的 UITextField 的 CGFrame?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55869942/

相关文章:

ios - 将 NSMeasurement 或 NSUnit 存储在 Core Data 中

ios - 如何在 Swift 中注册我自己的根证书颁发机构?

ios - UITextField 数字键盘 : dot instead of comma for float values

ios - 尝试删除包含拒绝辞职的第一响应者的行

iphone - UITextField 如何检查是否按下了删除键

android - Facebook API 2.1 - 关于邀请好友和应用范围内的用户 ID

ios - AMSlideMenu 侧边菜单打开时通知

xcode - 为什么 block 参数没有自动完成?

swift - 为什么 Xcode 告诉我添加 .map { $0.rawValue } 而我只能做 ?.rawValue?

ios - 在 podspec 中启用 static_framework 会破坏现有应用程序吗?