Swift: 无法让 UITextField 关闭键盘
Swift: Can't get UITextField to dismiss keyboard
我的 VC 中有两个 textFields
和一个 Done
按钮,但我在结束编辑时遇到了一些问题。
当我进入另一个 textField
之后点击一个 textField
时,或者当我在 textField 外部点击时(因为我在父视图中添加了点击识别器),我的 textFieldDidEndEditing
方法被调用但不是当我点击 Done
按钮时。
而且,最重要的是(尤其是当我在实际设备上 运行 时),键盘在任何这些情况下都不会消失,即使我的 textFieldDidEndEditing
方法调用 resignFirstResponder()
.
为什么键盘没有消失?另外,有没有办法让 textFieldDidEndEditing
在我自动点击字段外时被调用(而不是来自点击识别器)?看起来应该是这样的,但如果我错了,我就错了。
这是我的代码的一些相关部分。
1.Trying 关闭键盘。此方法的第一部分起作用,并存储值(即在调用该方法时)。光标在任何时候都不会从 textField 中消失,键盘也不会消失。
func textFieldDidEndEditing(_ textField: UITextField) {
if let playerName = textField.text, let playerNum = nameFields.index(of: textField) {
playerNames[playerNum] = playerName
}
resignFirstResponder()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textFieldDidEndEditing(textField)
return true
}
此外,还有一件奇怪的事情:当我在 textFieldDidEndEditing
中设置断点并调试时,在一个字段中输入一个值并点击 Done
,它会转到下一个场景,并且 然后停在textFieldDidEndEditing
,此时没有效果(值可能会被存储,但不会反映在新场景中)。
2.Trying 将点击识别器添加到完成按钮。我的代码中没有完成按钮的出口,只是出于懒惰,所以这可能是最好的解决方案。但是,我仍然对为什么这不起作用感兴趣。这与定义在父视图中工作的点击识别器的代码相同。
func dismiss(_ sender:UITapGestureRecognizer) {
nameFields.forEach { textFieldDidEndEditing([=12=]) }
}
override func viewDidAppear(_ animated: Bool) {
for view in view.subviews where view is UIButton {
let dismissTextField = UITapGestureRecognizer(target: self, action: #selector(dismiss(_:)))
dismissTextField.numberOfTapsRequired = 1
view.addGestureRecognizer(dismissTextField)
}
}
您需要在 textFieldShouldReturn
方法中调用 resignFirstResponder
而不是调用 textFieldDidEndEditing
.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
此外,在您的 TapGesture
方法中,只需使用 view
调用 endEditing(_:)
,而不是循环遍历文本字段数组。
func dismiss(_ sender:UITapGestureRecognizer) {
self.view.endEditing(true)
}
Swift 5:下面这个解法其实简单多了
只需将带有文本字段的 ViewController 子类化为 UITextFieldDelegate,如下所示:
class CreateGroupViewController: UIViewController, UITextFieldDelegate {
然后,如果您将 UITextFields 命名为:nameTextField & occupationTextField,然后将以下委托添加到您的 viewDidLoad() 方法中:
self.nameTextField.delegate = self
self.occupationTextField.delegate = self
然后只需将通用函数添加到您的文件中即可:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
如果您这样做,那么对于您创建的每个 textField 引用插座,无论用户输入哪个 textField,它们都将在用户点击 return 按钮后隐藏键盘。对于您添加到视图中的每个文本字段,将另一个 self.nextTextField.delegate = self 行添加到您的 viewDidLoad.
请记住将 iPhone/iDevice 插入您的开发人员计算机进行测试,因为 XCode 的模拟器不会调出键盘(因为您通常使用全键盘进行测试)。或者,如果您已经通过 WiFi 设置了测试硬件 (iPhone),您也可以这样做。否则,您的用户将在 TestFlight 上 "testing"。
我的 VC 中有两个 textFields
和一个 Done
按钮,但我在结束编辑时遇到了一些问题。
当我进入另一个 textField
之后点击一个 textField
时,或者当我在 textField 外部点击时(因为我在父视图中添加了点击识别器),我的 textFieldDidEndEditing
方法被调用但不是当我点击 Done
按钮时。
而且,最重要的是(尤其是当我在实际设备上 运行 时),键盘在任何这些情况下都不会消失,即使我的 textFieldDidEndEditing
方法调用 resignFirstResponder()
.
为什么键盘没有消失?另外,有没有办法让 textFieldDidEndEditing
在我自动点击字段外时被调用(而不是来自点击识别器)?看起来应该是这样的,但如果我错了,我就错了。
这是我的代码的一些相关部分。
1.Trying 关闭键盘。此方法的第一部分起作用,并存储值(即在调用该方法时)。光标在任何时候都不会从 textField 中消失,键盘也不会消失。
func textFieldDidEndEditing(_ textField: UITextField) {
if let playerName = textField.text, let playerNum = nameFields.index(of: textField) {
playerNames[playerNum] = playerName
}
resignFirstResponder()
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textFieldDidEndEditing(textField)
return true
}
此外,还有一件奇怪的事情:当我在 textFieldDidEndEditing
中设置断点并调试时,在一个字段中输入一个值并点击 Done
,它会转到下一个场景,并且 然后停在textFieldDidEndEditing
,此时没有效果(值可能会被存储,但不会反映在新场景中)。
2.Trying 将点击识别器添加到完成按钮。我的代码中没有完成按钮的出口,只是出于懒惰,所以这可能是最好的解决方案。但是,我仍然对为什么这不起作用感兴趣。这与定义在父视图中工作的点击识别器的代码相同。
func dismiss(_ sender:UITapGestureRecognizer) {
nameFields.forEach { textFieldDidEndEditing([=12=]) }
}
override func viewDidAppear(_ animated: Bool) {
for view in view.subviews where view is UIButton {
let dismissTextField = UITapGestureRecognizer(target: self, action: #selector(dismiss(_:)))
dismissTextField.numberOfTapsRequired = 1
view.addGestureRecognizer(dismissTextField)
}
}
您需要在 textFieldShouldReturn
方法中调用 resignFirstResponder
而不是调用 textFieldDidEndEditing
.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
此外,在您的 TapGesture
方法中,只需使用 view
调用 endEditing(_:)
,而不是循环遍历文本字段数组。
func dismiss(_ sender:UITapGestureRecognizer) {
self.view.endEditing(true)
}
Swift 5:下面这个解法其实简单多了
只需将带有文本字段的 ViewController 子类化为 UITextFieldDelegate,如下所示:
class CreateGroupViewController: UIViewController, UITextFieldDelegate {
然后,如果您将 UITextFields 命名为:nameTextField & occupationTextField,然后将以下委托添加到您的 viewDidLoad() 方法中:
self.nameTextField.delegate = self
self.occupationTextField.delegate = self
然后只需将通用函数添加到您的文件中即可:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
如果您这样做,那么对于您创建的每个 textField 引用插座,无论用户输入哪个 textField,它们都将在用户点击 return 按钮后隐藏键盘。对于您添加到视图中的每个文本字段,将另一个 self.nextTextField.delegate = self 行添加到您的 viewDidLoad.
请记住将 iPhone/iDevice 插入您的开发人员计算机进行测试,因为 XCode 的模拟器不会调出键盘(因为您通常使用全键盘进行测试)。或者,如果您已经通过 WiFi 设置了测试硬件 (iPhone),您也可以这样做。否则,您的用户将在 TestFlight 上 "testing"。