Responder Chain: คืออะไร หลักการทำงาน และห่วงโซ่ผู้ตอบสนอง

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-07-09 เวลาอ่าน: 9 นาที

Responder Chain เป็นกลไกของ iOS ที่ส่งต่อเหตุการณ์การสัมผัส การกดแป้นพิมพ์ และท่าทางตามลำดับผ่านลำดับชั้นของออบเจ็กต์ UIResponder จนกว่าหนึ่งในนั้นจะจัดการกับเหตุการณ์ ห่วงโซ่เริ่มต้นด้วยออบเจ็กต์ที่ตรวจพบเหตุการณ์และเคลื่อนที่ขึ้นไปตามลำดับชั้น: จาก view ไปยัง superview จากนั้นไปยัง view controller, window และสุดท้ายไปยัง UIApplication ตาม Apple Developer Documentation (2026) รูปแบบนี้ช่วยแยกความรับผิดชอบในการจัดการเหตุการณ์ระหว่างส่วนประกอบอินเทอร์เฟซ ให้ความยืดหยุ่นโดยไม่ต้องผูกติดกับตัวจัดการเฉพาะ

ประเด็นสำคัญ

  • Responder Chain — ห่วงโซ่ตามลำดับชั้นของออบเจ็กต์ UIResponder สำหรับส่งต่อเหตุการณ์ตามลำดับจากผู้ตอบสนองคนแรกไปยัง UIApplication
  • Hit-Testing กำหนดว่าออบเจ็กต์ใดจะเป็นอันแรกในห่วงโซ่ผู้ตอบสนองโดยการวิเคราะห์การซ้อนกันของ view ที่จุดสัมผัส
  • แต่ละ UIResponder สามารถจัดการเหตุการณ์หรือส่งต่อตามห่วงโซ่ผ่านเมธอด next
  • UIApplication เป็นโหนดสุดท้ายของห่วงโซ่: หากไม่มีออบเจ็กต์ใดจัดการเหตุการณ์ มันจะถูกละทิ้ง
  • ตัวจัดการที่กำหนดเอง ถูกสร้างขึ้นโดยการโอเวอร์ไรด์เมธอด touchesBegan, touchesMoved, touchesEnded ในคลาสย่อยของ UIView หรือ UIViewController

Responder Chain คืออะไร

Responder Chain คือลำดับของออบเจ็กต์ UIResponder ที่ iOS ใช้ส่งต่อเหตุการณ์อินพุต เช่น การสัมผัส การกดแป้นพิมพ์ และข้อมูล accelerometer ออบเจ็กต์แต่ละตัวในห่วงโซ่นี้มีความสามารถในการจัดการเหตุการณ์หรือส่งต่อไปยังออบเจ็กต์ผู้ตอบสนองถัดไปผ่านคุณสมบัติ next

กลไกนี้ขึ้นอยู่กับลำดับชั้นของ view: เมื่อมีการสัมผัสเกิดขึ้น iOS จะกำหนดก่อนว่า view ใดถูกสัมผัส (ผ่าน hit-testing) และสร้างห่วงโซ่เริ่มจาก view นั้นขึ้นไปจนถึง UIApplication UIApplication คือจุดเชื่อมต่อสุดท้ายของห่วงโซ่ — หากเหตุการณ์มาถึงและไม่ได้รับการจัดการ มันจะถูกละทิ้ง

ตามข้อมูลของ Apple รูปแบบนี้มีความสำคัญอย่างยิ่งสำหรับ การห่อหุ้มตรรกะการจัดการเหตุการณ์ นักพัฒนาสามารถโอเวอร์ไรด์พฤติกรรมของ view เฉพาะได้โดยไม่ส่งผลกระทบต่อองค์ประกอบอื่น ๆ ในลำดับชั้น ตัวอย่างเช่น UITextField จะกลายเป็นผู้ตอบสนองคนแรกเมื่อได้รับโฟกัสและรับเหตุการณ์แป้นพิมพ์โดยไม่ต้องเปลี่ยนแปลงใน UIViewController หลัก

Responder Chain จัดการเหตุการณ์อย่างไร

การจัดการเหตุการณ์ ผ่าน Responder Chain เกิดขึ้นในสองขั้นตอน: ก่อนอื่น iOS กำหนดว่า view ใดได้รับเหตุการณ์ (hit-testing) จากนั้นจึงเรียกใช้ห่วงโซ่ผู้ตอบสนองเพื่อจัดการ หากออบเจ็กต์ไม่ได้ใช้เมธอดที่เกี่ยวข้อง เหตุการณ์จะถูกส่งต่อ

ห่วงโซ่ถูกสร้างขึ้นแบบไดนามิกตามผู้ตอบสนองคนแรกปัจจุบันและลำดับชั้นของ view ลำดับมาตรฐานคือ: ผู้ตอบสนองคนแรก → 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 สิ่งนี้ทำให้นักพัฒนาควบคุมได้อย่างสมบูรณ์ว่าออบเจ็กต์ใดมีส่วนร่วมในการจัดการ

การส่งต่อเหตุการณ์ระหว่างออบเจ็กต์ผู้ตอบสนอง

เมื่อออบเจ็กต์ได้รับเหตุการณ์แต่ไม่ได้จัดการ (ไม่ได้โอเวอร์ไรด์เมธอด) iOS จะส่งต่อเหตุการณ์ไปยังออบเจ็กต์ผู้ตอบสนองถัดไปโดยอัตโนมัติผ่านคุณสมบัติ next คุณสมบัตินี้สร้างรายการเชื่อมโยงเดี่ยว ซึ่งเรียกว่า Responder Chain

UIViewController อยู่ระหว่าง view ของมันกับ UIWindow: หาก view ไม่จัดการเหตุการณ์ ตัวควบคุมจะมีโอกาสจัดการ สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับ ตรรกะร่วม — ตัวอย่างเช่น การจัดการท่าทางที่ควรทำงานทั่วทั้งฉาก โดยไม่ขึ้นกับว่า view ใดอยู่ใต้นิ้วของผู้ใช้

Hit-Testing: จากการสัมผัสสู่ผู้ตอบสนองคนแรก

Hit-Testing คือกระบวนการที่ iOS ใช้กำหนดว่า view ใดอยู่ใต้จุดสัมผัส เมธอด hitTest:withEvent: จะสำรวจลำดับชั้นของ view จาก UIWindow ลงไปด้านล่าง ตรวจสอบว่า view ย่อยใดมีจุดสัมผัสและไม่ถูกซ่อน

อัลกอริทึมทำงานแบบเรียกซ้ำ: สำหรับแต่ละระดับ iOS จะตรวจสอบ view ในลำดับย้อนกลับของการเพิ่ม (บนสุดก่อน) หาก view ไม่ถูกซ่อน ไม่โปร่งใส และจุดอยู่ในขอบเขตของมัน 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 สำหรับห่วงโซ่ผู้ตอบสนอง

UIResponder คือคลาสพื้นฐานสำหรับออบเจ็กต์ทั้งหมดที่สามารถจัดการเหตุการณ์ใน iOS UIView, UIViewController, UIApplication และ UIWindow สืบทอดจาก UIResponder คลาสนี้มีชุดเมธอดที่สามารถโอเวอร์ไรด์เพื่อจัดการเหตุการณ์ประเภทต่าง ๆ

กลุ่มเมธอดหลักประกอบด้วย touchesBegan, touchesMoved, touchesEnded, touchesCancelled สำหรับการสัมผัส; pressesBegan, pressesEnded สำหรับปุ่มกายภาพ; และ motionBegan, motionEnded สำหรับเหตุการณ์ accelerometer แต่ละเมธอด จะได้รับชุดออบเจ็กต์ 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 — หากเพิ่มตัวรู้จำท่าทางลงใน view มันจะได้รับเหตุการณ์ก่อน

ตามข้อมูลของ Apple การใช้ Responder Chain อย่างถูกต้องมีความสำคัญอย่างยิ่งสำหรับ การเข้าถึง ของแอป VoiceOver และเทคโนโลยีช่วยเหลืออื่น ๆ ใช้ห่วงโซ่ผู้ตอบสนองเพื่อนำทางระหว่างองค์ประกอบอินเทอร์เฟซ หากห่วงโซ่ขาด ผู้ใช้ที่มีความพิการจะไม่สามารถโต้ตอบกับแอปพลิเคชันได้

UIMenuController และ Responder Chain

UIMenuController สำหรับแสดงเมนูบริบทก็ใช้ Responder Chain เช่นกัน เมื่อผู้ใช้เรียกเมนู ระบบจะมองหาผู้ตอบสนองคนแรกที่ใช้เมธอด canPerformAction และเมธอดการดำเนินการที่เกี่ยวข้อง เมนูจะแสดงเฉพาะสำหรับการดำเนินการที่ผู้ตอบสนองปัจจุบันรองรับ

สิ่งนี้ช่วยให้ ตัวอย่างเช่น แสดงคำสั่งตัด คัดลอก วาง เฉพาะเมื่อ UITextField อยู่ในโฟกัส และซ่อนเมื่อทำงานกับ UILabel นักพัฒนาสามารถเพิ่มการดำเนินการที่กำหนดเองลงในเมนูบริบทโดยการimplement ในคลาสย่อยของ 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 มาตรฐาน คุณต้องระบุอย่างชัดเจนว่าออบเจ็กต์ใดจะเป็น next responder ของมัน สิ่งนี้ช่วยให้แน่ใจว่าเหตุการณ์ที่ไม่ได้รับการจัดการ将继续เคลื่อนที่ไปตาม Responder Chain

คำถามที่พบบ่อย

Responder Chain ใน iOS คืออะไร?

Responder Chain คือห่วงโซ่ตามลำดับชั้นของออบเจ็กต์ UIResponder ที่ iOS ใช้ส่งต่อเหตุการณ์การสัมผัส การกด และท่าทางตามลำดับ หากออบเจ็กต์ไม่จัดการเหตุการณ์ มันจะถูกส่งต่อไปยังออบเจ็กต์ผู้ตอบสนองถัดไปในห่วงโซ่จนถึง UIApplication

จะเปลี่ยนลำดับของห่วงโซ่ผู้ตอบสนองได้อย่างไร?

คุณสามารถเปลี่ยนลำดับได้โดยการโอเวอร์ไรด์คุณสมบัติ next ของออบเจ็กต์ UIResponder ของคุณ โดยการส่งคืนออบเจ็กต์อื่นแทนค่าเริ่มต้น คุณจะเปลี่ยนเส้นทางเหตุการณ์ที่ไม่ได้รับการจัดการไปยังมัน สิ่งนี้มีประโยชน์สำหรับลำดับชั้นที่ไม่เป็นมาตรฐาน เช่น เมื่อคอนเทนเนอร์ที่กำหนดเองจัดการตัวควบคุมย่อยหลายตัว

ความแตกต่างระหว่าง hit-test และ responder chain คืออะไร?

Hit-Testing กำหนดว่า view ใดอยู่ใต้จุดสัมผัส (ผู้รับเริ่มต้น) ในขณะที่ Responder Chain กำหนดว่าเหตุการณ์ถูกส่งต่อระหว่างออบเจ็กต์หลังจาก hit-test อย่างไร Hit-test ค้นหาออบเจ็กต์แรก ห่วงโซ่ผู้ตอบสนองให้การกำหนดเส้นทางเพิ่มเติมหากออบเจ็กต์นั้นไม่จัดการเหตุการณ์

จะขัดจังหวะห่วงโซ่ผู้ตอบสนองได้อย่างไร?

เพื่อขัดจังหวะห่วงโซ่ เพียงจัดการเหตุการณ์ใน UIResponder ของคุณและ ไม่เรียก super ตัวอย่างเช่น โดยการโอเวอร์ไรด์ touchesBegan และไม่เรียก super.touchesBegan คุณป้องกันไม่ให้เหตุการณ์ถูกส่งต่อ เหตุการณ์จะถูกจัดการในระดับปัจจุบันและจะไม่ถึงจุดเชื่อมต่อถัดไปของห่วงโซ่

ทำไม view ของฉันไม่ได้รับการสัมผัส?

สาเหตุที่พบบ่อยที่สุด: isUserInteractionEnabled ถูกตั้งค่าเป็น false, view ถูกซ่อน (isHidden = true), alpha น้อยกว่า 0.01 หรือ view อยู่นอกขอบเขตของคอนเทนเนอร์หลัก นอกจากนี้ให้ตรวจสอบว่าไม่มี UIGestureRecognizer บน view หรือ superview ของมันที่สกัดกั้นเหตุการณ์ก่อน touchesBegan

สรุป

  • Responder Chain เป็นกลไกพื้นฐานของ iOS สำหรับกำหนดเส้นทางเหตุการณ์อินพุตผ่านลำดับชั้น UIResponder จากผู้ตอบสนองคนแรกไปยัง UIApplication
  • Hit-Testing เกิดขึ้นก่อน Responder Chain และกำหนดว่า view ใดจะได้รับเหตุการณ์ก่อนโดยการวิเคราะห์ลำดับชั้นและพิกัดการสัมผัส
  • UIResponder มีเมธอด touchesBegan, touchesMoved, touchesEnded, touchesCancelled, pressesBegan และอื่น ๆ สำหรับจัดการเหตุการณ์ประเภทต่าง ๆ
  • การเรียก super ในเมธอดการจัดการเหตุการณ์กำหนดว่าเหตุการณ์จะดำเนินต่อไปตามห่วงโซ่หรือจะถูกจัดการในระดับปัจจุบัน
  • ส่วนประกอบ UIKit (UITextField, UIButton, UITableView) ใช้ Responder Chain อย่างแข็งขันสำหรับพฤติกรรมมาตรฐาน รวมถึงแป้นพิมพ์และเมนูบริบท
  • UIResponder ที่กำหนดเอง ช่วยให้จัดการเหตุการณ์เฉพาะที่ไม่สามารถทำได้ด้วย UIGestureRecognizer มาตรฐาน
  • การกำหนดค่าที่ถูกต้อง ของ next responder ช่วยให้แน่ใจว่าเหตุการณ์ที่ไม่ได้รับการจัดการไปถึงตัวจัดการที่เหมาะสมในลำดับชั้นของแอปพลิเคชัน

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม