Как скрыть клавиатуру в Swift: полное руководство для разработчиков

При нажатии на UITextField или UITextView в iOS-приложении клавиатура автоматически появляется, но часто требуется скрыть её программно — например, после завершения ввода, при нажатии на фон или по кнопке "Готово". Стандартное поведение SwiftUI и UIKit не всегда интуитивно: если просто вызвать resignFirstResponder() на неактивном поле, клавиатура останется на экране, а при неправильной обработке жестов приложение может крашиться с ошибкой unrecognized selector.

Проблема усложняется в iOS 17+, где Apple изменила логику отображения клавиатуры для UIScrollView и модальных окон. Например, если скрывать клавиатуру в viewDidLoad(), это сработает только для первого поля ввода, а для динамически создаваемых элементов потребуется отдельная обработка. В этой статье разберём 5 надёжных способов скрытия клавиатуры — от базовых до продвинутых, с учётом особенностей Swift 5.9 и последних версий Xcode.

1. Базовый метод: resignFirstResponder()

Самый простой способ скрыть клавиатуру — вызвать метод resignFirstResponder() на активном текстовом поле. Этот метод сообщает системе, что поле больше не является "первым респондером" (т.е. не принимает ввод с клавиатуры). Однако здесь есть нюансы:

  • 🔹 Работает только если поле уже активно (т.е. клавиатура отображается).
  • 🔹 Не скрывает клавиатуру, если поле не в фокусе (например, после перехода на другой экран).
  • 🔹 В SwiftUI требует обёртки в UIHostingController.

Пример для UIKit:

@IBOutlet weak var textField: UITextField!

// Скрыть клавиатуру по нажатию на кнопку

@IBAction func hideKeyboard(_ sender: UIButton) {

textField.resignFirstResponder()

}

Для динамически создаваемых полей (например, в UITableView) нужно хранить ссылку на активное поле или использовать UIResponder цепочку:

override func touchesBegan(_ touches: Set, with event: UIEvent?) {

view.endEditing(true) // Скрывает клавиатуру для всех полей во view

}

2. Скрытие клавиатуры по тапу на фон (UITapGestureRecognizer)

Частая задача — скрывать клавиатуру при тапе на любую область экрана, кроме полей ввода. Для этого добавляем UITapGestureRecognizer к корневому UIView. Важно настроить делегата жеста, чтобы он не конфликтовал с другими интерактивными элементами (например, кнопками или UICollectionView).

Пример с настройкой в viewDidLoad():

override func viewDidLoad() {

super.viewDidLoad()

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboardOnTap))

tapGesture.cancelsTouchesInView = false // Разрешает обработку тапов вложенными view

view.addGestureRecognizer(tapGesture)

}

@objc func hideKeyboardOnTap() {

view.endEditing(true)

}

  • 📱 Подходит для экранов с множеством полей ввода (например, формы регистрации).
  • ⚠️ Не работает, если поверх UIView лежит модальное окно или UIAlertController.
  • 🔧 Для SwiftUI используйте модификатор .onTapGesture { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) }.
📊 Какой способ скрытия клавиатуры вы используете чаще?
resignFirstResponder()
UITapGestureRecognizer
NotificationCenter
IQKeyboardManager
Другой

3. Отслеживание событий клавиатуры через NotificationCenter

Если нужно скрыть клавиатуру при определённых событиях (например, при скролле или смене ориентации экрана), подпишитесь на уведомления UIKeyboardWillHideNotification и UIKeyboardDidHideNotification. Это полезно для сложных интерфейсов, где клавиатура должна скрываться автоматически.

Пример кода:

override func viewWillAppear(_ animated: Bool) {

super.viewWillAppear(animated)

NotificationCenter.default.addObserver(

self,

selector: #selector(keyboardWillHide),

name: UIResponder.keyboardWillHideNotification,

object: nil

)

}

@objc func keyboardWillHide(notification: NSNotification) {

// Дополнительная логика (например, скролл к началу экрана)

print("Клавиатура скрывается")

}

deinit {

NotificationCenter.default.removeObserver(self)

}

Уведомление Когда вызывается Типичное использование
UIKeyboardWillShowNotification Перед появлением клавиатуры Сдвиг контента вверх
UIKeyboardDidShowNotification После появления клавиатуры Фиксация положения скролла
UIKeyboardWillHideNotification Перед скрытием клавиатуры Восстановление исходного положения view

Важно: В iOS 15+ Apple рекомендует использовать UIKeyboardLayoutGuide вместо ручной обработки уведомлений для адаптивного интерфейса.

4. Продвинутые решения: IQKeyboardManager и SwiftUI

Для крупных проектов с десятками экранов ручная обработка клавиатуры неэффективна. В этом случае используют сторонние библиотеки или встроенные инструменты SwiftUI.

4.1. IQKeyboardManager

Библиотека IQKeyboardManager автоматически управляет клавиатурой: скрывает её по тапу на фон, адаптирует UIScrollView и поддерживает кастомные toolbar’ы. Установка через CocoaPods:

pod 'IQKeyboardManagerSwift'

Минимальная настройка в AppDelegate:

import IQKeyboardManagerSwift

@main

class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

IQKeyboardManager.shared.enable = true

return true

}

}

4.2. SwiftUI: ключевые модификаторы

В SwiftUI клавиатура управляется через модификаторы:

  • 🔧 .keyboardType(.emailAddress) — настройка типа клавиатуры.
  • 🔧 .submitLabel(.done) — изменение текста кнопки "Готово".
  • 🔧 .onSubmit { hideKeyboard() } — действие при нажатии "Готово".

Пример скрытия клавиатуры в SwiftUI:

struct ContentView: View {

@State private var text = ""

@FocusState private var isFocused: Bool

var body: some View {

TextField("Введите текст", text: $text)

.focused($isFocused)

.toolbar {

ToolbarItemGroup(placement: .keyboard) {

Spacer()

Button("Готово") {

isFocused = false // Скрывает клавиатуру

}

}

}

}

}

☑️ Проверка перед использованием IQKeyboardManager

Выполнено: 0 / 5

5. Распространённые ошибки и их решения

Даже опытные разработчики сталкиваются с проблемами при работе с клавиатурой. Вот типичные ошибки и способы их исправления:

⚠️ Внимание: Если клавиатура не скрывается после вызова resignFirstResponder(), проверьте, не блокирует ли её модальное окно или алерт. В этом случае сначала закройте алерт, затем скрывайте клавиатуру.
Ошибка Причина Решение
Клавиатура не скрывается при тапе на фон Жест UITapGestureRecognizer не добавлен или перекрыт другим view Проверьте порядок добавления жестов (view.addGestureRecognizer должен быть после инициализации дочерних view)
Крэш при вызове resignFirstResponder() Поле ввода (UITextField) равно nil или уже деинициализировано Используйте view.endEditing(true) вместо прямого вызова
Клавиатура появляется снова после скрытия Автофокус на другое поле (например, в UITableView) Отключите автофокус или обработайте переход между полями

Ещё одна частая проблема — клавиатура не скрывается в UIScrollView при прокрутке. Решение:

scrollView.keyboardDismissMode = .interactive // или .onDrag

6. Оптимизация для разных версий iOS

Поведение клавиатуры менялось в разных версиях iOS. Например, в iOS 13 появился UIKeyboardLayoutGuide, а в iOS 16 — новые модификаторы для SwiftUI. Чтобы код работал универсально, используйте проверки версии:

Пример адаптивного кода:

if #available(iOS 15.0, *) {

// Используем UIKeyboardLayoutGuide для iOS 15+

let guide = view.keyboardLayoutGuide

someConstraint = view.bottomAnchor.constraint(equalTo: guide.topAnchor)

} else {

// Старый способ для iOS 14 и ниже

NotificationCenter.default.addObserver(

self,

selector: #selector(keyboardWillShow),

name: UIResponder.keyboardWillShowNotification,

object: nil

)

}

Для SwiftUI в iOS 16+ доступен новый модификатор .scrollDismissalBehavior, который автоматически скрывает клавиатуру при скролле:

ScrollView {

// Контент

}

.scrollDismissalBehavior(.immediately)

Как тестировать скрытие клавиатуры на симуляторе

1. Запустите приложение в Xcode симуляторе (Cmd + R).

2. Нажмите на текстовое поле, чтобы вызвать клавиатуру.

3. Для имитации тапа на фон используйте мышь или трекпад.

4. Чтобы проверить скрытие по кнопке "Готово", нажмите Command + K в симуляторе (это эквивалент нажатия на клавиатуре).

5. Для тестирования скролла используйте мышь или жесты трекпада.

6. Проверьте логи в консоли Xcode (Cmd + Shift + C) на наличие ошибок типа "unrecognized selector".

7. Альтернативные подходы: кастомные клавиатуры и Input Accessory View

Если стандартные методы не подходят, можно создать кастомную клавиатуру или использовать inputAccessoryView. Это полезно для:

  • 🎨 Некстандартного дизайна (например, клавиатура с эмодзи).
  • 🔒 Дополнительных кнопок (сканирование QR, вставка шаблонов).
  • 📱 Оптимизации под специфичные задачи (например, калькулятор в банковских приложениях).

Пример добавления inputAccessoryView:

let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 50))

toolbar.barStyle = .default

let doneButton = UIBarButtonItem(title: "Готово", style: .done, target: self, action: #selector(doneButtonTapped))

toolbar.items = [doneButton]

toolbar.sizeToFit()

textField.inputAccessoryView = toolbar

@objc func doneButtonTapped() {

textField.resignFirstResponder()

}

Для полной кастомизации клавиатуры потребуется создать subclass UIInputViewController и настроить его в Info.plist:

<key>NSExtension</key>

<dict>

<key>NSExtensionAttributes</key>

<dict>

<key>UIKeyboardHasFullAccess</key>

<false/>

</dict>

</dict>

FAQ: Частые вопросы по скрытию клавиатуры в Swift

Почему клавиатура не скрывается после вызова resignFirstResponder()?

Вероятные причины:

  1. Поле ввода не является первым респондером (проверьте через textField.isFirstResponder).
  2. Клавиатура принадлежит другому полю (например, в UITableView с несколькими ячейками).
  3. Конфликт с анимацией или модальным окном (попробуйте view.endEditing(true)).

Решение: используйте UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) для скрытия клавиатуры глобально.

Как скрыть клавиатуру при прокрутке UIScrollView?

Начиная с iOS 10, можно использовать свойство keyboardDismissMode:

scrollView.keyboardDismissMode = .interactive // или .onDrag

Для более ранних версий iOS добавьте обработчик жеста скролла:

scrollView.panGestureRecognizer.addTarget(self, action: #selector(handleScroll))
Можно ли скрыть клавиатуру анимацией?

Да, для этого используйте UIView.animate вместе с resignFirstResponder():

UIView.animate(withDuration: 0.3) {

self.view.layoutIfNeeded()

self.textField.resignFirstResponder()

}

Однако учтите, что сама клавиатура скрывается с системной анимацией, которую нельзя переопределить.

Как скрыть клавиатуру в SwiftUI при нажатии на кнопку?

Используйте @FocusState:

struct ContentView: View {

@State private var text = ""

@FocusState private var isFocused: Bool

var body: some View {

VStack {

TextField("Текст", text: $text)

.focused($isFocused)

Button("Скрыть клавиатуру") {

isFocused = false

}

}

}

}

Почему клавиатура появляется снова после поворота экрана?

Это происходит из-за автоматического восстановления фокуса системой. Решения:

  • Отключите автофокус в viewWillTransition(to:with:).
  • Сохраните состояние фокуса перед поворотом и восстановите его после.
  • Используйте UIKeyboardWillHideNotification для принудительного скрытия.