First Responder هو كائن UIResponder في iOS يستقبل أولاً أحداث اللمس وضغطات المفاتيح وإيماءات الاهتزاز وأوامر القائمة. في أي لحظة، يمكن لكائن واحد فقط في التطبيق أن يكون first responder. يحدث التعيين تلقائياً (عند تركيز UITextField) أو برمجياً عبر طريقة becomeFirstResponder. وفقاً لوثائق مطوري Apple (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: يلمس المستخدم حقل إدخال — تظهر لوحة المفاتيح؛ يضغط زر العودة أو يلمس حقلاً آخر — تتبدل لوحة المفاتيح أو تُخفى. يمكن للمطور التحكم في ذلك عبر طرق UIResponder، وكذلك عبر inputView و inputAccessoryView لاستبدال لوحة المفاتيح القياسية بأخرى مخصصة.
Input Accessory View هي لوحة إضافية فوق لوحة المفاتيح مرتبطة أيضاً بـ first responder. على سبيل المثال، لوحة بأزرار التالي والسابق وتم للتنقل بين حقول الإدخال. تظهر وتُخفى مع لوحة المفاتيح، متزامنة مع حالة first responder.
| الحدث | حالة first responder | لوحة المفاتيح |
|---|---|---|
| لمس UITextField | يصبح first responder | تظهر |
| الضغط على زر العودة | يبقى أو يستقيل | تبقى أو تُخفى |
| لمس حقل آخر | ينتقل إلى الحقل الجديد | تتبدل |
| استدعاء resignFirstResponder | تُزال | تُخفى |
| إخفاء التطبيق | يستقيل تلقائياً | تُخفى |
ResignFirstResponder هي طريقة UIResponder تزيل حالة first responder من الكائن. بعد الاستدعاء، يتوقف الكائن عن استقبال أحداث الإدخال، وتُخفى لوحة المفاتيح (إذا كانت نشطة). ترجع الطريقة Bool — true إذا كانت الاستقالة ناجحة.
غالباً ما يستدعي المطورون resignFirstResponder استجابةً للضغط على زر تم، أو لمس منطقة فارغة من الشاشة (view.endEditing)، أو عند مغادرة الشاشة. view.endEditing(true) هي طريقة مناسبة لاستقالة جميع حقول النص الفرعية مرة واحدة: فهي تجتاز التسلسل الهرمي للعروض بالكامل وتستدعي resignFirstResponder على first responder الحالي.
// الاستقالة عند الضغط على زر تم
@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 بمرجع ضعيف (weak reference) إلى 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. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا