Responder Chain: این چیست، اصل کار و زنجیره پاسخ‌دهندگان

نویسنده: IT Sectr منتشر شده: 2026-07-09 زمان مطالعه: 9 دقیقه

Responder Chain یک مکانیسم iOS است که رویدادهای لمس، فشار کلیدها و جست‌ها را به‌صورت متوالی از طریق سلسله‌مراتب اشیاء UIResponder انتقال می‌دهد، تا اینکه یکی از آن‌ها رویداد را پردازش کند. زنجیره از شیئی که رویداد را کشف کرده آغاز می‌شود و در سلسله‌مراتب به بالا حرکت می‌کند: از view به superview آن، سپس به view controller، window و در نهایت به UIApplication. به گزارش Apple Developer Documentation (2026)، این الگو به شما امکان تقسیم مسئولیت پردازش رویدادها را بین کامپوننت‌های رابط می‌دهد و انعطاف‌پذیری بدون اتصال سفت به یک handler خاص فراهم می‌کند.

نکات کلیدی

  • Responder Chain — یک زنجیره سلسله‌مراتبی از اشیاء UIResponder برای انتقال متوالی رویدادها از اولین responder تا UIApplication است.
  • Hit-Testing تعیین می‌کند که کدام شیء اولین در زنجیره responderها خواهد بود، با تجزیه و تحلیل توالد view در نقطه لمس.
  • هر UIResponder می‌تواند رویداد را پردازش کند یا آن را از طریق روش next در زنجیره انتقال دهد.
  • UIApplication گره پایانی زنجیره است: اگر هیچ شیئی رویداد را پردازش نکند، آن رد می‌شود.
  • handlerهای سفارشی با بازنویسی روش‌های touchesBegan، touchesMoved، touchesEnded در زیرکلاس‌های UIView یا UIViewController ایجاد می‌شوند.

Responder Chain چیست

Responder Chain یک تسلسل از اشیاء UIResponder است که iOS از طریق آن‌ها رویدادهای ورودی مانند لمس، فشار کلیدها و شتاب‌سنج را منتقل می‌کند. هر شیء در این زنجیره این قابلیت را دارد که رویداد را پردازش کند یا آن را به شیء responder بعدی از طریق ویژگی next انتقال دهد.

این مکانیسم بر اساس سلسله‌مراتب view استوار است: وقتی لمسی اتفاق می‌افتد، iOS ابتدا تعیین می‌کند که کدام view فشار داده شده ( از طریق hit-testing) و زنجیره‌ای از آن view تا UIApplication ایجاد می‌کند. UIApplication آخرین حلقه زنجیره است — اگر رویداد به آن برسد و پردازش نشود، صرفاً نادیده گرفته می‌شود.

به گزارش Apple، این الگو برای کپسوله‌سازی منطق پردازش رویدادها بسیار مهم است. توسعه‌دهنده می‌تواند رفتار یک view خاص را بدون تأثیر بر سایر عناصر سلسله‌مراتب بازنویسی کند. به عنوان مثال، UITextField با دریافت فوکوس به first responder تبدیل می‌شود و رویدادهای صفحه کلید را بدون نیاز به تغییرات در UIViewController والد دریافت می‌کند.

Responder Chain چگونه رویدادها را پردازش می‌کند

پردازش رویدادها از طریق Responder Chain در دو مرحله انجام می‌شود: ابتدا iOS تعیین می‌کند که کدام view رویداد را دریافت کرده (hit-testing)، سپس زنجیره responderها را برای پردازش آن آغاز می‌کند. اگر شیئی روش مناسب را پیاده‌سازی نکند، رویداد به بیشتر انتقال داده می‌شود.

زنجیره بر اساس first responder فعلی و سلسله‌مراتب view به صورت پویا شکل می‌گیرد. ترتیب ستاندارد به این صورت است: first responder → view آن → superview → UIViewController → root view → UIWindow → UIApplication. اگر هریک از این اشیاء به‌عنوان مثال touchesBegan را پیاده‌سازی کند، رویداد در آن سطح پردازش شده و بیشتر انتقال داده نمی‌شود.

swift
import UIKit

class CustomView: UIView {
    override func touchesBegan(
        _ touches: Set<UITouch>,
        with event: UIEvent?
    ) {
        // لمس در این سطح از view پردازش شد
        print("CustomView لمس را پردازش کرد")
        
        // رویداد را در طول زنجیره ارسال کن
        super.touchesBegan(touches, with: event)
    }
}

ویژگی کلیدی این است که فراخوانی super.touchesBegan اجباری نیست. اگر فراخوانی نشود، رویداد تنها در سطح جاری پردازش شده و از Responder Chain بیشتر نخواهد گذشت. این به توسعه‌دهنده کنترل کاملی بر اینکه کدام اشیاء در پردازش شرکت می‌کنند می‌دهد.

انتقال رویدادها بین اشیاء responder

وقتی شیئی رویدادی را دریافت می‌کند اما آن را پردازش نمی‌کند (روش را بازنویسی نمی‌کند)، iOS به طور خودکار رویداد را به شیء responder بعدی از طریق ویژگی next انتقال می‌دهد. این ویژگی یک لیست یکطرفه ایجاد می‌کند که Responder Chain نامیده می‌شود.

UIViewController بین view خود و UIWindow قرار دارد: اگر view رویداد را پردازش نکند، کنترلر شانس انجام این کار را دارد. این به‌ویژه برای منطق مشترک مفید است — به عنوان مثال، پردازش جستی که باید در تمام صفحه کار کند، صرف‌نظر از اینکه چه viewی زیر انگشت کاربر است.

Hit-Testing: از لمس تا اولین responder

Hit-Testing فرآیندی است که iOS به کمک آن تعیین می‌کند که کدام view در زیر نقطه لمس قرار دارد. روش hitTest:withEvent: سلسله‌مراتب view را از UIWindow به پایین پیمایش می‌کند و بررسی می‌کند که کدامیک از viewهای تابع نقطه لمس را شامل می‌شود و مخفی نیست.

الگوریتم به صورت بازگشتی کار می‌کند: برای هر سطح، iOS viewها را به ترتیب معکوس اضافه بررسی می‌کند (ابتدا بالایی‌ها). اگر view مخفی نباشد، شفاف نباشد و نقطه در bounds آن باشد، hitTest به صورت بازگشتی برای تمام subviewها فراخوانده می‌شود. عمیق‌ترین view که همه شرایط را برآورده کند، hit-test view می‌شود — اولین شیء در 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 را بازنویسی کنند تا رفتار ستاندارد را تغییر دهند. به عنوان مثال، منطقه لمس را برای یک دکمه کوچک گشتردن یا رویداد را به view دیگری که اصلاً زیر انگشت نیست هدایت کنید. این ابزاری قدرتمند برای ایجاد عناصر تعاملی سفارشی است.

روش‌های UIResponder برای زنجیره responderها

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 این روش‌ها را تنها برای first responder و اشیاء بعدی در زنجیره فراخوانده می‌کند. اگر هیچ شیئی روشی را بازنویسی نکرده باشد، رویداد خطا ایجاد نمی‌کند — صرفاً نادیده گرفته می‌شود. برای اشکال‌زدایی پردازش رویداد‌ها از Symbolic Breakpoint بر UIResponder touchEvent استفاده کنید.

Responder Chain و عناصر UIKit

کامپوننت‌های ستاندارد UIKit به طور فعالی از Responder Chain برای کار خود استفاده می‌کنند. UITextField با دریافت فوکوس به first responder تبدیل می‌شود که به طور خودکار صفحه کلید را باز می‌کند. UIButton لمس‌ها را از طریق مکانیسم UIControl پردازش می‌کند که آن نیز بر responder chain استوار است.

UITableView و UICollectionView از زنجیره responderها برای پردازش انتخاب سلول‌ها و جست‌های پیمایش استفاده می‌کنند. اگر کاربر سلولی را لمس کند، رویداد را ابتدا خود سلول، سپس UITableView و فقط بعد از آن UIViewController دریافت می‌کند. UIGestureRecognizer اولویت بالاتری از touchesBegan دارد — اگر به view یک شناساینده جست اضافه شود، آن ابتدا رویداد را دریافت خواهد کرد.

به گزارش Apple، استفاده صحیح از Responder Chain برای دسترس‌پذیری برنامه بسیار مهم است. VoiceOver و سایر فناوری‌های کمکی از زنجیره responderها برای پیمایش بین عناصر رابط استفاده می‌کنند. اگر زنجیره شکسته شود، کاربران محدود نمی‌توانند با برنامه تعامل کنند.

UIMenuController و Responder Chain

UIMenuController برای نمایش منوی کتکستی نیز از Responder Chain استفاده می‌کند. وقتی کاربر منو را فراخوان می‌کند، سیستم به دنبال first responderی می‌گردد که روش‌های canPerformAction و روش‌های عمل مناسب را پیاده‌سازی کند. منو تنها برای اعمالی نمایش داده می‌شود که responder فعلی آن‌ها را پشتیبانی می‌کند.

این به عنوان مثال امکان نمایش دستورات برش، رونویسی، چسبانن را تنها وقتی که UITextField در فوکوس است و پنهان کردن آن‌ها هنگام کار با UILabel فراهم می‌کند. توسعه‌دهنده می‌تواند با پیاده‌سازی آن‌ها در زیرکلاس UIResponder و بازگرداندن true از canPerformAction، اعمال سفارشی را به منوی کتکستی اضافه کند.

اشیاء responder سفارشی در iOS

ایجاد یک شیء responder سفارشی به توسعه‌دهنده کنترل کاملی بر پردازش رویدادها می‌دهد. برای این کار باید یک زیرکلاس UIResponder (یا UIView/UIViewController) ایجاد کرده و روش‌های مورد نیاز پردازش رویداد را بازنویسی کنید.

اشیاء responder سفارشی معمولاً برای پردازش جست‌های ویژه استفاده می‌شوند که توسط UIGestureRecognizer ستاندارد پوشش داده نمی‌شوند. به عنوان مثال، تشخیص کشیدن اشکال، ترکیبات پیچیده multi-touch یا الگوهای ورودی انحصاری. یک responder سفارشی می‌تواند رویدادها را از چندین انگشت جمع‌آوری کرده و بر اساس ترکیب آن‌ها تصمیم گیری کند.

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)
        }
    }
}

هنگام ایجاد یک responder سفارشی، پیکربندی مناسب زنجیره next مهم است. اگر شیء شما بخشی از سلسله‌مراتب ستاندارد UIKit نیست، باید صریحاً مشخص کنید که کدام شیء next responder آن خواهد بود. این تضمین می‌کند که رویدادهای پردازش‌نشده به حرکت خود در Responder Chain ادامه دهند.

سؤالات متداول

Responder Chain در iOS چیست؟

Responder Chain یک زنجیره سلسله‌مراتبی از اشیاء UIResponder است که iOS از طریق آن رویدادهای لمس، فشار و جست را به طور متوالی انتقال می‌دهد. اگر شیئی رویداد را پردازش نکند، آن به شیء responder بعدی در زنجیره تا UIApplication انتقال داده می‌شود.

چگونه می‌توان ترتیب زنجیره responderها را تغییر داد؟

ترتیب را می‌توان با بازنویسی ویژگی next در شیء UIResponder خود تغییر داد. با بازگرداندن شیء دیگری به جای شیء ستاندارد، رویدادهای پردازش‌نشده را به آن هدایت می‌کنید. این برای سلسله‌مراتب‌های غیراستاندارد مفید است، به عنوان مثال وقتی یک کانتینر سفارشی چندین کنترلر تابع را مدیریت می‌کند.

تفاوت بین hit-test و responder chain چیست؟

Hit-Testing تعیین می‌کند که کدام view در زیر نقطه لمس قرار دارد (دریافت کننده اصلی)، و Responder Chain تعیین می‌کند چگونه رویداد بین اشیاء بعد از hit-test انتقال داده می‌شود. Hit-test اولین شیء را پیدا می‌کند، responder chain اگر آن شیء رویداد را پردازش نکند مسیریابی بیشتر را فراهم می‌کند.

چگونه می‌توان زنجیره responderها را قطع کرد؟

برای قطع زنجیره، کافی است رویداد را در UIResponder خود پردازش کرده و super را فراخوان نکنید. به عنوان مثال، با بازنویسی touchesBegan و فراخوان نکردن super.touchesBegan، از انتقال رویداد به بیشتر جلوگیری می‌کنید. رویداد در سطح جاری پردازش شده و به حلقه‌های بعدی زنجیره نمی‌رسد.

چرا view من لمس را دریافت نمی‌کند؟

شایع‌ترین دلایل: isUserInteractionEnabled به false تنظیم شده، view مخفی است (isHidden = true)، alpha کمتر از 0.01 است، یا view خارج از bounds کانتینر والد است. همچنین بررسی کنید که آیا روی view یا superview آن UIGestureRecognizerی وجود دارد که رویدادها را پیش از touchesBegan گیرنداری می‌کند.

نتیجهگیری

  • Responder Chain — یک مکانیسم بنیادین iOS برای مسیریابی رویدادهای ورودی از طریق سلسله‌مراتب UIResponder از first responder تا UIApplication است.
  • Hit-Testing قبل از Responder Chain انجام شده و تعیین می‌کند که کدام view ابتدا رویداد را دریافت خواهد کرد، با تجزیه و تحلیل سلسله‌مراتب و مختصات لمس.
  • UIResponder روش‌های touchesBegan، touchesMoved، touchesEnded، touchesCancelled، pressesBegan و سایر را برای پردازش انواع مختلف رویدادها فراهم می‌کند.
  • فراخوانی super در روش‌های پردازش رویداد تعیین می‌کند که انتقال در زنجیره ادامه می‌یابد یا رویداد در سطح جاری پردازش می‌شود.
  • کامپوننت‌های UIKit (UITextField، UIButton، UITableView) به طور فعال از Responder Chain برای رفتار ستاندارد از جمله صفحه کلید و منوهای کتکستی استفاده می‌کنند.
  • UIResponder سفارشی امکان پیاده‌سازی پردازش رویداد مخصوص را فراهم می‌کند که توسط UIGestureRecognizer ستاندارد پیش‌بینی نشده است.
  • تنظیم مناسب next responder تضمین می‌کند که رویدادهای پردازش‌نشده به handler مناسب در سلسله‌مراتب برنامه برسند.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید