带有文本字段的 UIAlertController:关闭键盘如何工作?

UIAlertController with textfield: how dismiss keyboard works?

在我的 UIViewController 子类中,我创建了一个 UIAlertControllerUITextField:

class MyViewController: UIViewController {
...

     let alertController = UIAlertController(title: "a title", message: "", preferredStyle: .alert)
     let okAction = UIAlertAction(title: "OK!", style: .default) { alert in
          print("OK!!")
     }
     alertController.addTextField { (textField) in
     textField.placeholder = "a placeholder"
     textField.delegate = self
     }
     alertController.addAction(okAction)
     self.present(alertController, animated: true, completion: nil)

...

}

extension MyViewController: UITextFieldDelegate {
      func textFieldShouldReturn(_ textField: UITextField) -> Bool {
          return true
      }
}

现在,当显示警报并且我点击键盘 next/done 按钮时,键盘和警报被关闭并且打印 OK!

在我的 textFieldShouldReturn 方法中既没有 textField.resignFirstResponder() 也没有警报解除命令,那么怎么可能解除键盘和警报呢?苹果如何实现这种行为?有 textField 两名代表吗?

实际上,你提的问题不够强烈。您可以删除您的分机和 textField.delegate = self 行,当用户点击 Return.

时,警报仍然会消失

该行为对于警报来说是自动的。除非您禁用关闭按钮,否则当用户在虚拟键盘中点击 Return 时默认情况下会为您点击它。

至于实际机制,是editingDidEndOnExit控制事件。这使您可以自由地设置委托而不会把事情搞砸。

我想了解 Apple UIAlertController 行为,以便在我正在实施的警报自定义控制器中添加相同的行为。在@matt 的回答帮助下,我想我明白了 UIAlertController 是如何工作的。在我的代码片段下方 connect 所有警报的文本字段:

guard let last = textFields.last else {
    return
}
for i in 0 ..< textFields.count - 1 {
    textFields[i].returnKeyType = .next
    textFields[i].addTarget(textFields[i+1], action: #selector(UIResponder.becomeFirstResponder), for: .editingDidEndOnExit)
}
last.returnKeyType = .done
last.addTarget(last, action: #selector(UIResponder.resignFirstResponder), for: .editingDidEndOnExit)

以这种方式,当我点击键盘 next/done 按钮并且最后一个文本字段是第一响应者时,键盘被关闭;否则下一个文本字段成为第一响应者。

这个 post 也有帮助。

,该行为对于包含文本字段的警报来说是正常的。 一旦您按下键盘上的 return 键,它就会触发 .editingDidEndOnExit,这将关闭键盘和警报。

您可以通过像这样删除 textField 上的目标来防止这种行为:

  textField.removeTarget(nil, action: nil, for: .editingDidEndOnExit)

一旦您点击键盘上的 return 键,这将不再关闭警报。