Responder Chain は、タッチ、キー入力、ジェスチャーイベントを UIResponder オブジェクトの階層を通じて順次渡し、いずれかのオブジェクトがイベントを処理するまで伝達する iOS の仕組みです。チェーンはイベントを検出したオブジェクトから始まり、ビューからそのスーパービュー、ビューコントローラー、ウィンドウ、そして最終的に UIApplication へと階層を上っていきます。Apple Developer Documentation (2026) によると、このパターンにより、インターフェースコンポーネント間でイベント処理の責任を分離し、特定のハンドラーに強く結びつけることなく柔軟性を提供します。
重要なポイント
Responder Chain は、iOS がタッチ、キー入力、加速度計データなどの入力イベントを渡す一連の UIResponder オブジェクトです。このチェーンの各オブジェクトは、イベントを処理するか、next プロパティを介して次のレスポンダーオブジェクトに渡すことができます。
この仕組みはビュー階層に基づいています。タッチが発生すると、iOS は最初にどのビューがタッチされたかを判断し(ヒットテストによる)、そのビューから UIApplication までのチェーンを作成します。UIApplication はチェーンの最後のリンクです。イベントがそこに到達して処理されない場合、単に破棄されます。
Apple によると、このパターンは イベント処理ロジックのカプセル化 にとって重要です。開発者は、階層内の他の要素に影響を与えることなく、特定のビューの動作をオーバーライドできます。たとえば、UITextField はフォーカスを受け取るとファーストレスポンダーになり、親の UIViewController を変更することなくキーボードイベントを受け取ります。
イベント処理 は、Responder Chain を介して 2 段階で行われます。まず、iOS はどのビューがイベントを受け取ったかを判断し(ヒットテスト)、次にレスポンダーチェーンを実行して処理します。オブジェクトが対応するメソッドを実装していない場合、イベントはさらに渡されます。
チェーンは、現在のファーストレスポンダーとビュー階層に基づいて動的に形成されます。標準の順序は次のとおりです。ファーストレスポンダー → そのビュー → スーパービュー → UIViewController → ルートビュー → UIWindow → UIApplication。これらのオブジェクトのいずれかが、たとえば touchesBegan を実装している場合、イベントはそのレベルで処理され、それ以上渡されません。
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 は、iOS がタッチポイントの下にあるビューを決定するプロセスです。hitTest:withEvent: メソッドは、UIWindow から下に向かってビュー階層を走査し、どの子ビューがタッチポイントを含み、非表示でないかを確認します。
アルゴリズムは再帰的に機能します。各レベルで、iOS は追加順序の逆順でビューをチェックします(最初に最上部)。ビューが非表示でなく、透明でなく、ポイントがその bounds 内にある場合、そのすべてのサブビューに対して再帰的に hitTest が実行されます。すべての条件を満たす最も深いビュー がヒットテストビューになり、Responder Chain の最初のオブジェクトになります。
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 は、iOS でイベントを処理できるすべてのオブジェクトの基本クラスです。UIView、UIViewController、UIApplication、UIWindow は UIResponder を継承しています。このクラスは、さまざまなタイプのイベントを処理するためにオーバーライドできる一連のメソッドを提供します。
主要なメソッドグループには、タッチ用の touchesBegan、touchesMoved、touchesEnded、touchesCancelled、物理ボタン用の pressesBegan、pressesEnded、加速度計イベント用の motionBegan、motionEnded が含まれます。各メソッド は、UITouch または UIPress オブジェクトのセットと、イベントに関する追加メタデータを含む UIEvent への参照を受け取ります。
| UIResponder メソッド | 目的 |
|---|---|
| touchesBegan | タッチ開始時に呼び出される |
| touchesMoved | 指の移動時に呼び出される |
| touchesEnded | 指を離したときに呼び出される |
| touchesCancelled | 割り込み時に呼び出される(電話、コントロールセンタースワイプ) |
| pressesBegan | 物理ボタン押下時に呼び出される |
iOS はこれらのメソッドを ファーストレスポンダー とチェーン内の後続のオブジェクトに対してのみ呼び出すことに注意してください。どのオブジェクトもメソッドをオーバーライドしていない場合、イベントはエラーを発生させず、単に無視されます。イベント処理をデバッグするには、UIResponder touchEvent にシンボリックブレークポイントを使用します。
標準の UIKit コンポーネント は、その動作のために Responder Chain を積極的に使用しています。UITextField はフォーカスを受け取るとファーストレスポンダーになり、自動的にキーボードを開きます。UIButton は UIControl メカニズムを介してタッチを処理しますが、これもレスポンダーチェーンに依存しています。
UITableView と UICollectionView は、セル選択とスクロールジェスチャーの処理にレスポンダーチェーンを使用します。ユーザーがセルをタッチすると、イベントは最初にセル自体に届き、次に UITableView、そして最後に UIViewController に届きます。UIGestureRecognizer は touchesBegan よりも優先度が高く、ビューにジェスチャー認識子が追加されている場合、それが最初にイベントを受け取ります。
Apple によると、Responder Chain の適切な使用は アプリのアクセシビリティ にとって重要です。VoiceOver やその他の支援技術は、インターフェース要素間のナビゲーションにレスポンダーチェーンを使用します。チェーンが壊れていると、障がいのあるユーザーはアプリケーションを操作できなくなります。
UIMenuController はコンテキストメニューを表示するためにも Responder Chain を使用します。ユーザーがメニューを呼び出すと、システムは canPerformAction と対応するアクションメソッドを実装するファーストレスポンダーを探します。メニューは、現在のレスポンダーがサポートするアクションに対してのみ表示されます。
これにより、たとえば、UITextField がフォーカスされている場合にのみ切り取り、コピー、貼り付けコマンドを表示し、UILabel での作業時には非表示にすることができます。開発者は、UIResponder のサブクラスでこれらを実装し、canPerformAction から true を返すことで、コンテキストメニューにカスタムアクションを追加できます。
カスタムレスポンダー オブジェクトを作成すると、開発者はイベント処理を完全に制御できます。これを行うには、UIResponder(または UIView/UIViewController)のサブクラスを作成し、必要なイベント処理メソッドをオーバーライドする必要があります。
カスタムレスポンダーオブジェクトは、標準の UIGestureRecognizer ではカバーされない 特定のジェスチャー を処理するためによく使用されます。たとえば、図形描画の認識、複雑なマルチタッチの組み合わせ、独自の入力パターンなどです。カスタムレスポンダーは、複数の指からのイベントを集約し、その組み合わせに基づいて決定を下すことができます。
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 がタッチ、プレス、ジェスチャーイベントを順次渡す UIResponder オブジェクトの階層チェーンです。オブジェクトがイベントを処理しない場合、チェーンに沿って次のレスポンダーオブジェクトに UIApplication まで渡されます。
UIResponder オブジェクトの next プロパティをオーバーライドすることで順序を変更できます。デフォルトの代わりに別のオブジェクトを返すことで、未処理のイベントをそのオブジェクトにリダイレクトします。これは、カスタムコンテナが複数の子コントローラーを管理する場合など、非標準の階層に便利です。
Hit-Testing はタッチポイントの下にあるビュー(最初の受信者)を決定し、Responder Chain は hit-test 後にイベントがオブジェクト間でどのように渡されるかを決定します。Hit-test が最初のオブジェクトを見つけ、そのオブジェクトがイベントを処理しない場合、レスポンダーチェーンがさらなるルーティングを提供します。
チェーンを中断するには、UIResponder でイベントを処理し、super を呼び出さない ようにします。たとえば、touchesBegan をオーバーライドして super.touchesBegan を呼び出さないことで、イベントがさらに渡されるのを防ぎます。イベントは現在のレベルで処理され、チェーンの次のリンクには到達しません。
最も一般的な理由は次のとおりです。isUserInteractionEnabled が false に設定されている、ビューが非表示(isHidden = true)、alpha が 0.01 未満、またはビューが親コンテナの bounds 外にある。また、ビューまたはそのスーパービューに touchesBegan より前にイベントをインターセプトする UIGestureRecognizer がないか確認してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。