First Responder — е обект UIResponder в iOS, който пръв получава събития на докосване, натискания на клавиши, жестове за разклащане и команди от меню. Всеки момент само един обект в приложението може да бъде first responder. Назначаването става автоматично (при фокус на UITextField) или програмно чрез метода becomeFirstResponder. Според Apple Developer Documentation (2026), обект може да стане first responder само ако методът му canBecomeFirstResponder връща true, което прави този механизъм явен и контролируем.
Основни точки
First Responder — е обект UIResponder, който в момента приема входни събития в iOS приложение. Системата насочва всички събития на докосване, натискания на клавиши, движения (разклащане на устройството) и действия (например извикване на контекстно меню) точно към този обект.
Концепцията first responder е първото звено в Responder Chain. Ако first responder не обработи полученото събитие, то автоматично се предава на следващия обект във веригата. Това гарантира, че събитието не се губи, а последователно се предлага на всички потенциални обработващи в йерархията.
Според Apple, статусът first responder е тясно свързан с UIResponder и неговите методи canBecomeFirstResponder и becomeFirstResponder. По подразбиране UIView връща true само за определени подкласове — UITextField, UITextView, UISearchBar. Други изгледи, включително обикновен UIView, връщат false, което предотвратява случайно назначаване.
Назначаване на first responder може да стане по два начина: автоматично, когато потребителят докосне UITextField (системата вътрешно извиква becomeFirstResponder), или програмно, когато разработчикът изрично извика метода becomeFirstResponder на който и да е UIResponder обект.
Преди назначаване iOS проверява canBecomeFirstResponder. Ако методът върне false, извикването на becomeFirstResponder се игнорира и обектът не става first responder. Това е защитен механизъм, предотвратяващ назначаването на обекти, които не са готови да обработват събития — например скрити или деактивирани елементи на интерфейса.
class CustomTextField: UITextField {
override var canBecomeFirstResponder: Bool {
return super.canBecomeFirstResponder
}
}
// Програмно назначаване
textField.becomeFirstResponder()
// Проверка дали е first responder
if textField.isFirstResponder {
print("TextField вече е first responder")
}
При назначаване на нов first responder iOS автоматично извиква resignFirstResponder на предишния. Това гарантира, че в системата винаги има само един обект със статус first responder. Ако новият обект не може да стане first responder (canBecomeFirstResponder = false), старият запазва статуса си.
iOS клавиатура се появява на екрана благодарение на механизма first responder. Когато UITextField или UITextView стане first responder, системата автоматично показва клавиатурата, свързана с текущия keyboardType на това поле. При отказване на first responder клавиатурата се скрива.
Това поведение е ключов UX механизъм в iOS: потребителят докосва поле за въвеждане — клавиатурата се появява; натиска Return или докосва друго поле — клавиатурата се превключва или скрива. Разработчикът може да управлява това чрез UIResponder методи, както и чрез inputView и inputAccessoryView за замяна на стандартната клавиатура с персонализирана.
Input Accessory View — е допълнителен панел над клавиатурата, който също е свързан с first responder. Например панел с бутони Next, Previous, Done за навигация между полетата за въвеждане. Той се показва и скрива заедно с клавиатурата, синхронизирайки се със статуса на first responder.
| Събитие | Статус first responder | Клавиатура |
|---|---|---|
| Докосване на UITextField | Става first responder | Появява се |
| Натискане на Return | Остава или се отказва | Остава или се скрива |
| Докосване на друго поле | Преминава към новото поле | Превключва се |
| Извикване на resignFirstResponder | Премахва се | Скрива се |
| Скриване на приложението | Автоматично се отказва | Скрива се |
ResignFirstResponder — е метод на UIResponder, който премахва статуса first responder от обект. След извикване обектът спира да получава входни събития, а клавиатурата (ако е била активна) се скрива. Методът връща Bool — true, ако отказването е успешно.
Разработчиците често извикват resignFirstResponder в отговор на натискане на бутона Done, докосване на празна област на екрана (view.endEditing) или при напускане на екрана. view.endEditing(true) — е удобен начин за отказване на всички дъщерни текстови полета наведнъж: преминава през цялата йерархия от изгледи и извиква resignFirstResponder на текущия first responder.
// Отказване при натискане на Done
@objc func doneButtonTapped() {
textField.resignFirstResponder()
}
// Отказване при докосване на празна област
override func touchesBegan(
_ touches: Set<UITouch>,
with event: UIEvent?
) {
view.endEditing(true)
}
// Отказване за всички полета на формуляра
func validateAndSubmit() {
view.endEditing(true)
// Логика за изпращане на формуляр
}
Съществуват ситуации, когато resignFirstResponder може да върне false. Това се случва, ако обектът е преопределил метода и изрично е забранил премахването на статуса. Например, текстово поле в процес на валидация може временно да блокира отказването, за да предотврати загуба на данни. В такива случаи трябва да се изчака завършването на валидацията и едва тогава да се принуди отказване.
UIResponder предоставя свойството isFirstResponder (само за четене), което връща true, ако даденият обект в момента е first responder. Това е полезно за условна логика — например, да не се изпълнява действие, ако текстово поле е на фокус и потребителят въвежда данни.
iOS не предоставя вграден API за получаване на текущия first responder в мащаба на цялото приложение. Разработчиците създават тази възможност чрез обхождане на йерархията от изгледи с помощта на UIResponder метода. Решението на Apple препоръчва слаба препратка към first responder, която може да се актуализира чрез KVO или делегати.
// Разширение за намиране на first responder
extension UIView {
var firstResponder: UIResponder? {
guard isFirstResponder else {
return subviews.compactMap { $0.firstResponder }.first
}
return self
}
}
// Употреба
if let current = view.firstResponder {
print("Current first responder: \(current)")
}
За проследяване на промени на first responder можете да се абонирате за уведомленията UIResponder.keyboardWillShowNotification и UIResponder.keyboardWillHideNotification — те индиректно показват, че някакъв текстов обект е станал или е престанал да бъде first responder. Въпреки това, няма директно абониране за промяна на isFirstResponder; за това се използва KVO или персонализирани делегати.
Персонализирани изгледи могат да станат first responder, ако преопределят canBecomeFirstResponder и върнат true. Това е необходимо за компоненти, които трябва да приемат събития от клавиатура или физически бутони — например персонализирани игрови контролери или редактори на код, базирани на UITextView.
При създаване на персонализиран first responder е важно да се помни за достъпността: VoiceOver и Switch Control разчитат на правилното назначаване на first responder за навигация. Ако персонализиран изглед стане first responder, той трябва правилно да имплементира протокола UIAccessibility и да информира асистивните технологии за статуса си.
За персонализирано въвеждане (например скенер за баркодове или цифрова клавиатура) преопределете свойството inputView — върнете персонализиран UIView, който ще се показва вместо стандартната клавиатура, когато този изглед е first responder. Аналогично, inputAccessoryView добавя панел над клавиатурата.
Често задавани въпроси
First Responder — е обект UIResponder, който в момента получава входни събития (докосвания, клавиши, акселерометър). Назначава се чрез becomeFirstResponder, трябва да връща true от canBecomeFirstResponder. Само един обект може да бъде first responder в приложението.
Извикайте textField.becomeFirstResponder() програмно, например в viewDidAppear. Уверете се, че textField не е скрит, userInteractionEnabled = true и isEnabled = true. Ако полето е в UITableView или UICollectionView, уверете се, че клетката е видима на екрана.
Добавете UITapGestureRecognizer към основния изглед и в неговия манипулатор извикайте view.endEditing(true). Това автоматично ще намери текущия first responder и ще извика resignFirstResponder. Алтернативно, преопределете touchesBegan в UIViewController с извикване на endEditing.
becomeFirstResponder връща false, ако canBecomeFirstResponder връща false, изгледът е скрит, не е в йерархията на прозореца или userInteractionEnabled = false. Също така проверете дали изгледът е добавен към прозореца — изглед, който не е на екрана, няма да работи с becomeFirstResponder.
iOS не предоставя глобален API за това. Използвайте рекурсивно обхождане на йерархията от изгледи чрез разширение на UIView, което проверява isFirstResponder за всеки подизглед. Алтернатива — съхранявайте слаба препратка към последния first responder в AppDelegate и я актуализирайте чрез UITextField делегати.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също