First Responder — это объект UIResponder в iOS, который первым получает события касания, нажатий клавиш, shake-жестов и команд меню. В каждый момент времени только один объект в приложении может быть first responder. Назначение происходит автоматически (при фокусе UITextField) или программно через метод becomeFirstResponder. По данным Apple Developer Documentation (2026), объект может стать first responder только если его метод canBecomeFirstResponder возвращает true, что делает этот механизм явным и контролируемым.
Главное
First Responder — это объект UIResponder, который в данный момент принимает события ввода в iOS-приложении. Система направляет все события касания, нажатия клавиш, motion-события (встряхивание устройства) и action-сообщения (например, вызов контекстного меню) именно этому объекту.
Концепция first responder является первым звеном в Responder Chain. Если first responder не обрабатывает полученное событие, оно автоматически передаётся следующему объекту в цепочке. Это гарантирует, что событие не потеряется, а будет последовательно предложено всем потенциальным обработчикам в иерархии.
По данным Apple, статус first responder тесно связан с UIResponder и его методами canBecomeFirstResponder и becomeFirstResponder. По умолчанию UIView возвращает true только для определённых подклассов — UITextField, UITextView, UISearchBar. Другие view, включая обычный UIView, возвращают false, что предотвращает случайное назначение.
Назначение first responder может происходить двумя способами: автоматически, когда пользователь касается UITextField (система вызывает becomeFirstResponder внутри), или программно, когда разработчик явно вызывает метод becomeFirstResponder на любом UIResponder-объекте.
Перед назначением iOS проверяет canBecomeFirstResponder. Если метод возвращает false, вызов becomeFirstResponder игнорируется, и объект не становится first responder. Это защитный механизм, предотвращающий назначение объектов, которые не готовы обрабатывать события — например, скрытых или отключённых элементов интерфейса.
class CustomTextField: UITextField {
override var canBecomeFirstResponder: Bool {
return super.canBecomeFirstResponder
}
}
// Programmatic assignment
textField.becomeFirstResponder()
// Check if first responder
if textField.isFirstResponder {
print("TextField is now first responder")
}
При назначении нового first responder iOS автоматически вызывает resignFirstResponder у предыдущего. Это гарантирует, что в системе всегда только один объект со статусом first responder. Если новый объект не может стать first responder (canBecomeFirstResponder = false), старый сохраняет свой статус.
Клавиатура iOS появляется на экране именно благодаря механизму first responder. Когда UITextField или UITextView становится first responder, система автоматически отображает клавиатуру, связанную с текущей keyboardType этого поля. При resign first responder клавиатура скрывается.
Это поведение является ключевым UX-механизмом в iOS: пользователь касается поля ввода — клавиатура появляется; нажимает Return или касается другого поля — клавиатура переключается или скрывается. Разработчик может управлять этим через UIResponder методы, а также через inputView и inputAccessoryView для замены стандартной клавиатуры кастомной.
Input Accessory View — это дополнительная панель над клавиатурой, которая также привязана к first responder. Например, панель с кнопками Next, Previous, Done для навигации между полями ввода. Она отображается и скрывается вместе с клавиатурой, синхронизируясь со статусом first responder.
| Событие | Статус first responder | Клавиатура |
|---|---|---|
| Касание UITextField | Становится first responder | Появляется |
| Нажатие Return | Остаётся или resign | Остаётся или скрывается |
| Касание другого поля | Переходит к новому полю | Переключается |
| Вызов resignFirstResponder | Снимается | Скрывается |
| Скрытие приложения | Автоматически resign | Скрывается |
ResignFirstResponder — это метод UIResponder, который снимает с объекта статус first responder. После вызова объект перестаёт получать события ввода, а клавиатура (если она была активна) скрывается. Метод возвращает Bool — true, если resign прошёл успешно.
Разработчики часто вызывают resignFirstResponder в ответ на нажатие кнопки Done, касание пустой области экрана (view.endEditing) или при уходе с экрана. view.endEditing(true) — удобный способ resign для всех дочерних текстовых полей сразу: он проходит по всей иерархии view и вызывает resignFirstResponder у текущего first responder.
// Resign on Done button tap
@objc func doneButtonTapped() {
textField.resignFirstResponder()
}
// Resign on empty area tap
override func touchesBegan(
_ touches: Set<UITouch>,
with event: UIEvent?
) {
view.endEditing(true)
}
// Resign for all form fields
func validateAndSubmit() {
view.endEditing(true)
// Form submission logic
}
Существуют ситуации, когда resignFirstResponder может вернуть false. Это происходит, если объект переопределил метод и явно запретил снятие статуса. Например, текстовое поле в процессе валидации может временно блокировать resign, чтобы предотвратить потерю данных. В таких случаях необходимо дождаться завершения валидации и только потом принудительно resign.
UIResponder предоставляет свойство isFirstResponder (read-only), которое возвращает true, если данный объект в данный момент является first responder. Это полезно для условной логики — например, чтобы не выполнять действие, если текстовое поле находится в фокусе и пользователь вводит данные.
iOS не предоставляет встроенного API для получения текущего first responder в масштабе всего приложения. Разработчики создают эту возможность через обход иерархии view с помощью UIResponder метода. Решение Apple рекомендует слабую ссылку на first responder, которую можно обновлять через KVO или делегаты.
// Extension to find first responder
extension UIView {
var firstResponder: UIResponder? {
guard isFirstResponder else {
return subviews.compactMap { $0.firstResponder }.first
}
return self
}
}
// Usage
if let current = view.firstResponder {
print("Current first responder: \(current)")
}
Для отслеживания изменений first responder можно подписаться на уведомления UIResponder.keyboardWillShowNotification и UIResponder.keyboardWillHideNotification — они косвенно указывают, что какой-то текстовый объект стал или перестал быть first responder. Однако прямой подписки на изменение isFirstResponder не существует; для этого используется KVO или кастомные делегаты.
Кастомные view могут стать first responder, если переопределить canBecomeFirstResponder и вернуть true. Это необходимо для компонентов, которые должны принимать события клавиатуры или физических кнопок — например, кастомные игровые контроллеры или редакторы кода на основе UITextView.
При создании кастомного first responder важно помнить о доступности: VoiceOver и Switch Control полагаются на правильное назначение first responder для навигации. Если кастомная view становится first responder, она должна корректно реализовать протокол UIAccessibility и сообщать ассистивным технологиям о своём статусе.
Для кастомного ввода (например, сканера штрихкодов или цифровой клавиатуры) переопределите свойство inputView — верните кастомную UIView, которая будет отображаться вместо стандартной клавиатуры, когда эта view является first responder. Аналогично, inputAccessoryView добавляет панель над клавиатурой.
Часто задаваемые вопросы
First Responder — это объект UIResponder, который в данный момент получает события ввода (касания, клавиши, акселерометр). Назначается через becomeFirstResponder, должен возвращать true из canBecomeFirstResponder. Только один объект может быть first responder в приложении.
Вызовите textField.becomeFirstResponder() программно, например, в viewDidAppear. Убедитесь, что textField не скрыт, userInteractionEnabled = true, и isEnabled = true. Если поле находится в UITableView или UICollectionView, убедитесь, что ячейка видна на экране.
Добавьте UITapGestureRecognizer на основную view и в его обработчике вызовите view.endEditing(true). Это автоматически найдёт current first responder и вызовет resignFirstResponder. Альтернативно переопределите touchesBegan у UIViewController с вызовом endEditing.
becomeFirstResponder возвращает false, если canBecomeFirstResponder возвращает false, view скрыта, не в иерархии window, или userInteractionEnabled = false. Также проверьте, что view добавлена в window — у view, не находящейся на экране, becomeFirstResponder не сработает.
iOS не предоставляет глобального API для этого. Используйте рекурсивный обход view hierarchy через расширение UIView, которое проверяет isFirstResponder у каждого subview. Альтернатива — хранить слабую ссылку на last first responder в AppDelegate и обновлять её через делегаты UITextField.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также