我在运行时动态地填充了许多UIScrollView
字段的垂直UITextField
。我遇到的问题是键盘将隐藏它将出现的区域中的字段,这可能包括我正在编辑的字段。
我尝试了来自苹果文档的KeyboardManagement解决方案,并尝试了关于textFieldDidBeginEditing
和textFieldDidEndEditing
的通知,但两种情况下的问题是keyboardWillShow
通知有时会出现,在这种情况下它不会让我知道哪个字段是编辑。
我在实现UITextFieldDelegate
协议的类中有这个代码,这个类的每个对象都包含对其中一个字段的引用,并且作为它的委托工作
func textFieldDidBeginEditing(_ textField: UITextField) {
self.activeTextfield = self.valueTextField
}
func textFieldDidEndEditing(_ textField: UITextField) {
self.activeTextfield = nil
}
activeTextfield
变量是对UIViewController
变量的弱引用,其中所有这些都发生了。在该视图控制器中,我有以下代码
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
委托方法吗?
这是处理这种情况的正确方法吗?
如果没有,我应该如何处理?
谢谢
如您的问题所述:
两种情况下的问题都是有时会出现keyboardWillShow通知,在这种情况下,它不会让我知道哪个字段是正在编辑的字段
根据苹果文档中描述的sequence of events,textFieldShouldBeginEditing
是第一个被称为的委托方法。
所以你可以
textFieldShouldBeginEditing
来设置你的活动文本字段,而不是textFieldDidBeginEditing
(确保你从textFieldShouldBeginEditing中获取return true
以允许编辑)keyboardDidShowNotification
而不是keyboardWillShowNotification
。这将确保您在获得键盘框架/细节之前标记了UITextField
。
您可以通过执行以下操作相当简单地完成此操作。首先会在视图中添加通知观察者。
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Keyboard notification
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
然后在你的选择器功能中你可以有这样的东西
@objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
let currentTextField = view.getSelectedTextField() {
let keyboardHeight = keyboardSize.height
let textFieldFrame = currentTextField.superview?.convert(currentTextField.frame, to: nil)
}
}
}
而你的getSelectedTextField()
扩展看起来像这样
// Inside UIView Extension
// Get currently active textfield
func getSelectedTextField() -> UITextField? {
let totalTextFields = getTextFieldsInView(view: self)
for textField in totalTextFields{
if textField.isFirstResponder{
return textField
}
}
return nil
}
func getTextFieldsInView(view: UIView) -> [UITextField] {
var totalTextFields = [UITextField]()
for subview in view.subviews as [UIView] {
if let textField = subview as? UITextField {
totalTextFields += [textField]
} else {
totalTextFields += getTextFieldsInView(view: subview)
}
}
return totalTextFields
}
}
您需要为textFields定义tag属性,并在textFieldDidBeginEditing
和textFieldDidEndEditing
中检查UITextField
被调用的内容。