Как скрыть клавиатуру в Swift при нажатии на Return в UITextField?
Решение: Использование делегата UITextFieldDelegate для скрытия клавиатуры
Ваш подход в целом правильный, но есть несколько нюансов, которые могут мешать корректной работе. Самая распространенная причина — неправильная настройка делегата в Interface Builder или неверная конфигурация самого текстового поля. Давайте разберем пошаговое решение.
Шаг 1: Настройка делегата в коде или Storyboard
Убедитесь, что ваш ViewController действительно является делегатом для UITextField. Есть два способа это сделать:
Способ A (программный, как у вас): Убедитесь, что метод viewDidLoad() вызывается и делегат назначается:
override func viewDidLoad() {
super.viewDidLoad()
nameTextField.delegate = self
}
Способ B (через Interface Builder): В сториборде выберите ваш UITextField, откройте Connections Inspector (иконка стрелки в правой панели) и перетащите от "delegate" на ViewController. Это эквивалентно программному назначению.
Шаг 2: Реализация метода делегата
Метод textFieldShouldReturn вызывается, когда пользователь нажимает Return. Внутри этого метода нужно вызвать resignFirstResponder() для текстового поля, которое в данный момент активно. Ваш код должен выглядеть так:
extension ViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Скрываем клавиатуру для текущего текстового поля
textField.resignFirstResponder()
// Возвращаем true, чтобы стандартное поведение (например, переход к следующему полю) было отменено
return true
}
}
Шаг 3: Дополнительная проверка — тип клавиши Return
Иногда проблема возникает, если для UITextField установлен неправильный тип клавиши Return. В сториборде выберите ваше текстовое поле, откройте Attributes Inspector и в секции "Text Input Traits" найдите параметр "Return Key". Убедитесь, что он установлен как "Default" или "Done", а не "Next" или "Go", если вы не планируете обрабатывать эти действия отдельно.
Шаг 4: Проверка на множественные текстовые поля
Если у вас несколько UITextField, и вы хотите, чтобы клавиатура скрывалась при нажатии Return на любом из них, вы можете использовать общий метод, который проверяет, какое поле активно:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// Скрываем клавиатуру для любого поля
textField.resignFirstResponder()
// Альтернатива: если нужно перейти к следующему полю
// if textField == nameTextField {
// passwordTextField.becomeFirstResponder()
// } else {
// textField.resignFirstResponder()
// }
return true
}
Почему ваш код мог не работать?
- Делегат не назначен: Проверьте, что вы не удалили строку
nameTextField.delegate = selfслучайно, или что в сториборде действительно есть связь. - Двойное назначение: Если вы назначили делегат и в коде, и в сториборде, это нормально, но убедитесь, что нет конфликта.
- Метод не вызывается: Вы упомянули, что print срабатывает, значит метод вызывается. Тогда проблема именно в
resignFirstResponder(). Возможно, текстовое поле не является first responder по какой-то причине (например, его состояние disabled).
Если после всех проверок клавиатура всё ещё не скрывается, попробуйте добавить вызов view.endEditing(true) внутри метода:
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
view.endEditing(true) // Скрывает клавиатуру для всех полей ввода
return true
}
Этот метод гарантированно скроет клавиатуру, независимо от того, какое поле активно. Используйте его как запасной вариант.
<<Альтернативный подход: Использование view.endEditing()
Если по какой-то причине делегат не срабатывает или вы хотите более универсальное решение (например, для скрытия клавиатуры при нажатии на любое место экрана), можно использовать метод view.endEditing(_:). Этот метод заставляет все текстовые поля в иерархии view отказаться от статуса first responder.
Вот пример реализации для кнопки "Готово" или для жеста тапа:
override func viewDidLoad() {
super.viewDidLoad()
// Добавляем жест для скрытия клавиатуры при тапе вне текстового поля
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
view.addGestureRecognizer(tapGesture)
// Устанавливаем делегат
nameTextField.delegate = self
}
@objc func hideKeyboard() {
view.endEditing(true)
}
extension ViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
hideKeyboard()
return true
}
}
Преимущества: Этот подход работает для любого количества текстовых полей и не требует отдельной обработки для каждого. Он также полезен, если вы хотите скрыть клавиатуру при тапе на фон.
Недостатки: Если у вас сложная иерархия view с вложенными контейнерами, view.endEditing(true) может не сработать, если текстовое поле находится в дочернем view, которое не является прямым потомком основного view. В таком случае используйте UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) — это самый надежный, но менее элегантный способ.