Responder Chain: ما هو، مبدأ العمل وسلسلة المستجيبين

المؤلف: IT Sectr نُشر: 2026-07-09 وقت القراءة: 9 دق

Responder Chain هي آلية في iOS تقوم بنقل أحداث اللمس وضغطات المفاتيح والإيماءات بشكل تسلسلي عبر تسلسل هرمي لكائنات UIResponder حتى يقوم أحدها بمعالجة الحدث. تبدأ السلسلة بالكائن الذي اكتشف الحدث وتتحرك لأعلى في التسلسل الهرمي: من العرض إلى العرض الفائق، ثم إلى وحدة التحكم في العرض، ثم إلى النافذة، وأخيراً إلى UIApplication. وفقاً Apple Developer Documentation (2026)، يسمح هذا النمط بفصل مسؤولية معالجة الأحداث بين مكونات الواجهة، مما يوفر مرونة دون ربط صارم بمعالج معين.

النقاط الرئيسية

  • Responder Chain — سلسلة هرمية من كائنات UIResponder لنقل الأحداث بشكل تسلسلي من المستجيب الأول إلى UIApplication.
  • Hit-Testing يحدد أي كائن سيكون الأول في سلسلة المستجيبين من خلال تحليل تداخل العروض في نقطة اللمس.
  • كل UIResponder يمكنه معالجة حدث أو تمريره إلى الأمام في السلسلة عبر طريقة next.
  • UIApplication هو العقدة النهائية للسلسلة: إذا لم يعالج أي كائن الحدث، يتم التخلص منه.
  • المعالجات المخصصة يتم إنشاؤها عن طريق تجاوز طرق touchesBegan و touchesMoved و touchesEnded في الفئات الفرعية لـ UIView أو UIViewController.

ما هو Responder Chain

Responder Chain هي سلسلة من كائنات UIResponder التي يمرر iOS من خلالها أحداث الإدخال مثل اللمسات وضغطات المفاتيح وبيانات مقياس التسارع. كل كائن في هذه السلسلة لديه القدرة على معالجة الحدث أو تمريره إلى كائن المستجيب التالي عبر الخاصية next.

تعتمد الآلية على التسلسل الهرمي للعروض: عند حدوث لمسة، يحدد iOS أولاً أي عرض تم لمسه (من خلال hit-testing) وينشئ سلسلة تبدأ من ذلك العرض وتصعد إلى UIApplication. UIApplication هو الحلقة الأخيرة في السلسلة — إذا وصل إليه حدث ولم تتم معالجته، يتم التخلص منه ببساطة.

وفقاً لـ Apple، هذا النمط مهم جداً لتغليف منطق معالجة الأحداث. يمكن للمطور تجاوز سلوك عرض معين دون التأثير على العناصر الأخرى في التسلسل الهرمي. على سبيل المثال، يصبح UITextField المستجيب الأول عند تلقي التركيز ويتلقى أحداث لوحة المفاتيح دون الحاجة إلى تغييرات في UIViewController الأصلي.

كيف يعالج Responder Chain الأحداث

معالجة الأحداث من خلال Responder Chain تحدث على مرحلتين: أولاً، يحدد iOS أي عرض استقبل الحدث (hit-testing)، ثم يشغل سلسلة المستجيبين لمعالجته. إذا لم يقم كائن بتنفيذ الطريقة المقابلة، يتم تمرير الحدث إلى الأمام.

يتم تشكيل السلسلة ديناميكياً بناءً على المستجيب الأول الحالي والتسلسل الهرمي للعروض. الترتيب القياسي هو: المستجيب الأول → عرضه → العرض الفائق → UIViewController → العرض الجذري → UIWindow → UIApplication. إذا قام أي من هذه الكائنات بتنفيذ، على سبيل المثال، touchesBegan، تتم معالجة الحدث في ذلك المستوى ولا يتم تمريره إلى الأمام.

swift
import UIKit

class CustomView: UIView {
    override func touchesBegan(
        _ touches: Set<UITouch>,
        with event: UIEvent?
    ) {
        // تمت معالجة اللمس في مستوى العرض هذا
        print("CustomView قام بمعالجة اللمس")
        
        // تمرير الحدث على طول السلسلة
        super.touchesBegan(touches, with: event)
    }
}

ميزة رئيسية هي أن استدعاء super.touchesBegan ليس إلزامياً. إذا لم يتم استدعاؤه، ستتم معالجة الحدث فقط في المستوى الحالي ولن يستمر في Responder Chain. وهذا يعطي المطور تحكماً كاملاً في الكائنات التي تشارك في المعالجة.

نقل الأحداث بين كائنات المستجيب

عندما يستقبل كائن حدثاً لكنه لا يعالجه (لا يتجاوز الطريقة)، يقوم iOS تلقائياً بتمرير الحدث إلى كائن المستجيب التالي عبر الخاصية next. تشكل هذه الخاصية قائمة مرتبطة باتجاه واحد، والتي تسمى Responder Chain.

يقع UIViewController بين عرضه و UIWindow: إذا لم يعالج العرض الحدث، تحصل وحدة التحكم على فرصة للقيام بذلك. هذا مفيد بشكل خاص للمنطق المشترك — على سبيل المثال، معالجة إيماءة يجب أن تعمل عبر المشهد بأكمله، بغض النظر عن أي عرض تحت إصبع المستخدم.

Hit-Testing: من اللمس إلى المستجيب الأول

Hit-Testing هي العملية التي يحدد من خلالها iOS أي عرض يقع تحت نقطة اللمس. تقوم طريقة hitTest:withEvent: باجتياز التسلسل الهرمي للعروض من UIWindow إلى الأسفل، للتحقق من أي عرض فرعي يحتوي على نقطة اللمس وغير مخفي.

تعمل الخوارزمية بشكل متكرر: لكل مستوى، يتحقق iOS من العروض بترتيب عكسي للإضافة (الأعلى أولاً). إذا كان العرض غير مخفي وغير شفاف وتقع النقطة داخل حدوده، يتم تشغيل hitTest بشكل متكرر لجميع العروض الفرعية. أعمق عرض يستوفي جميع الشروط يصبح عرض hit-test — الكائن الأول في Responder Chain.

swift
override func hitTest(
    _ point: CGPoint,
    with event: UIEvent?
) -> UIView? {
    if isUserInteractionEnabled &&
        isHidden == false &&
        alpha > 0.01 &&
        point(inside: point, with: event) {
        return super.hitTest(point, with: event)
    }
    return nil
}

يمكن للمطورين تجاوز hitTest لتغيير السلوك الافتراضي. على سبيل المثال، لتوسيع منطقة اللمس لزر صغير أو إعادة توجيه الحدث إلى عرض آخر غير موجود فعلياً تحت الإصبع. هذه أداة قوية لإنشاء عناصر تفاعلية مخصصة.

طرق UIResponder لسلسلة المستجيبين

UIResponder هي الفئة الأساسية لجميع الكائنات التي يمكنها معالجة الأحداث في iOS. UIView و UIViewController و UIApplication و UIWindow ترث من UIResponder. توفر الفئة مجموعة من الطرق التي يمكن تجاوزها لمعالجة أنواع مختلفة من الأحداث.

تشمل مجموعات الطرق الرئيسية touchesBegan و touchesMoved و touchesEnded و touchesCancelled للمسات؛ pressesBegan و pressesEnded للأزرار المادية؛ و motionBegan و motionEnded لأحداث مقياس التسارع. كل طريقة تستقبل مجموعة من كائنات UITouch أو UIPress ومرجعاً إلى UIEvent يحتوي على بيانات وصفية إضافية حول الحدث.

طريقة UIResponderالغرض
touchesBeganيتم استدعاؤها عند بدء اللمس
touchesMovedيتم استدعاؤها عند تحريك الإصبع
touchesEndedيتم استدعاؤها عند رفع الإصبع
touchesCancelledيتم استدعاؤها عند الانقطاع (مكالمة، تمرير لوحة التحكم)
pressesBeganيتم استدعاؤها عند الضغط على زر مادي

من المهم فهم أن iOS يستدعي هذه الطرق فقط للمستجيب الأول والكائنات اللاحقة في السلسلة. إذا لم يقم أي كائن بتجاوز الطريقة، فإن الحدث لا يولد خطأ — يتم تجاهله ببساطة. لتصحيح أخطاء معالجة الأحداث، استخدم Symbolic Breakpoint على UIResponder touchEvent.

Responder Chain وعناصر UIKit

مكونات UIKit القياسية تستخدم بنشاط Responder Chain في عملها. يصبح UITextField المستجيب الأول عند تلقي التركيز، مما يفتح لوحة المفاتيح تلقائياً. يعالج UIButton اللمسات من خلال آلية UIControl، التي تعتمد أيضاً على سلسلة المستجيبين.

تستخدم UITableView و UICollectionView سلسلة المستجيبين لمعالجة اختيار الخلايا وإيماءات التمرير. إذا لمس المستخدم خلية، يصل الحدث أولاً إلى الخلية نفسها، ثم UITableView، وبعد ذلك فقط UIViewController. UIGestureRecognizer له أولوية أعلى من touchesBegan — إذا تمت إضافة معرف إيماءات إلى عرض، فسيستقبل الحدث أولاً.

وفقاً لـ Apple، الاستخدام الصحيح لـ Responder Chain مهم جداً لإمكانية الوصول للتطبيق. تستخدم VoiceOver والتقنيات المساعدة الأخرى سلسلة المستجيبين للتنقل بين عناصر الواجهة. إذا كانت السلسلة مقطوعة، فلن يتمكن المستخدمون ذوو الإعاقة من التفاعل مع التطبيق.

UIMenuController و Responder Chain

UIMenuController لعرض القوائم السياقية يستخدم أيضاً Responder Chain. عندما يستدعي المستخدم القائمة، يبحث النظام عن مستجيب أول يقوم بتنفيذ طرق canPerformAction وطرق الإجراء المقابلة. يتم عرض القائمة فقط للإجراءات التي يدعمها المستجيب الحالي.

يسمح هذا، على سبيل المثال، بإظهار أوامر قص ونسخ ولصق فقط عندما يكون UITextField في التركيز، وإخفائها عند العمل مع UILabel. يمكن للمطور إضافة إجراءات مخصصة إلى القائمة السياقية من خلال تنفيذها في فئة فرعية من UIResponder وإرجاع true من canPerformAction.

كائنات مستجيب مخصصة في iOS

إنشاء كائن مستجيب مخصص يمنح المطور تحكماً كاملاً في معالجة الأحداث. للقيام بذلك، تحتاج إلى إنشاء فئة فرعية من UIResponder (أو UIView/UIViewController) وتجاوز طرق معالجة الأحداث الضرورية.

غالباً ما تُستخدم كائنات المستجيب المخصصة لمعالجة إيماءات محددة غير مغطاة بواسطة UIGestureRecognizer القياسي. على سبيل المثال، التعرف على رسم الأشكال، مجموعات اللمس المتعدد المعقدة، أو أنماط الإدخال الخاصة. يمكن للمستجيب المخصص تجميع الأحداث من عدة أصابع واتخاذ القرارات بناءً على مجموعها.

swift
class DrawingResponder: UIResponder {
    private var activeTouches: [UITouch: CGPoint] = [:]
    
    override func touchesBegan(
        _ touches: Set<UITouch>,
        with event: UIEvent?
    ) {
        for touch in touches {
            activeTouches[touch] = touch.location(in: self)
        }
    }
    
    override func touchesMoved(
        _ touches: Set<UITouch>,
        with event: UIEvent?
    ) {
        for touch in touches {
            let currentPoint = touch.location(in: self)
            activeTouches[touch] = currentPoint
            drawLine(from: activeTouches[touch]!, to: currentPoint)
        }
    }
}

عند إنشاء مستجيب مخصص، من المهم تكوين سلسلة next بشكل صحيح. إذا كان كائنك ليس جزءاً من التسلسل الهرمي القياسي لـ UIKit، يجب عليك تحديد الكائن الذي سيكون المستجيب التالي له بشكل صريح. هذا يضمن أن الأحداث غير المعالجة تستمر في التحرك على طول Responder Chain.

الأسئلة الشائعة

ما هو Responder Chain في iOS؟

Responder Chain هي سلسلة هرمية من كائنات UIResponder يمرر من خلالها iOS بشكل تسلسلي أحداث اللمس والضغط والإيماءات. إذا لم يعالج كائن الحدث، يتم تمريره إلى كائن المستجيب التالي في السلسلة حتى UIApplication.

كيف يمكن تغيير ترتيب سلسلة المستجيبين؟

يمكنك تغيير الترتيب عن طريق تجاوز الخاصية next في كائن UIResponder الخاص بك. بإرجاع كائن مختلف بدلاً من الكائن الافتراضي، تقوم بإعادة توجيه الأحداث غير المعالجة إليه. هذا مفيد للتسلسلات الهرمية غير القياسية، على سبيل المثال، عندما يدير حاوية مخصصة عدة وحدات تحكم فرعية.

ما الفرق بين hit-test و responder chain؟

Hit-Testing يحدد أي عرض يقع تحت نقطة اللمس (المستقبل الأولي)، بينما Responder Chain يحدد كيفية تمرير الحدث بين الكائنات بعد hit-test. يجد Hit-test الكائن الأول، وتوفر responder chain التوجيه الإضافي إذا لم يعالج هذا الكائن الحدث.

كيف يمكن مقاطعة سلسلة المستجيبين؟

لمقاطعة السلسلة، قم ببساطة بمعالجة الحدث في UIResponder الخاص بك ولا تستدعي super. على سبيل المثال، عن طريق تجاوز touchesBegan وعدم استدعاء super.touchesBegan، تمنع تمرير الحدث إلى الأمام. ستتم معالجة الحدث في المستوى الحالي ولن يصل إلى الحلقات التالية من السلسلة.

لماذا لا يستقبل العرض الخاص بي اللمسات؟

الأسباب الأكثر شيوعاً: isUserInteractionEnabled مضبوط على false، العرض مخفي (isHidden = true)، alpha أقل من 0.01، أو العرض خارج حدود الحاوية الأصلية. تحقق أيضاً من عدم وجود UIGestureRecognizer على العرض أو العرض الفائق الخاص به يعترض الأحداث قبل touchesBegan.

الملخص

  • Responder Chain هي آلية أساسية في iOS لتوجيه أحداث الإدخال عبر التسلسل الهرمي UIResponder من المستجيب الأول إلى UIApplication.
  • Hit-Testing يسبق Responder Chain ويحدد أي عرض سيستقبل الحدث أولاً عن طريق تحليل التسلسل الهرمي وإحداثيات اللمس.
  • UIResponder يوفر طرق touchesBegan و touchesMoved و touchesEnded و touchesCancelled و pressesBegan وغيرها لمعالجة أنواع مختلفة من الأحداث.
  • استدعاء super في طرق معالجة الأحداث يحدد ما إذا كان الحدث سيستمر في السلسلة أو تتم معالجته في المستوى الحالي.
  • مكونات UIKit (UITextField, UIButton, UITableView) تستخدم بنشاط Responder Chain للسلوك القياسي، بما في ذلك لوحة المفاتيح والقوائم السياقية.
  • UIResponder المخصص يسمح بتنفيذ معالجة أحداث محددة غير متوفرة في UIGestureRecognizer القياسي.
  • التكوين الصحيح للمستجيب التالي يضمن أن الأحداث غير المعالجة تصل إلى المعالج المناسب في التسلسل الهرمي للتطبيق.

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا