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 resign แป้นพิมพ์จะซ่อน
พฤติกรรมนี้เป็น กลไก UX สำคัญ ใน iOS: ผู้ใช้แตะช่องป้อนข้อมูล — แป้นพิมพ์ปรากฏ กด Return หรือแตะช่องอื่น — แป้นพิมพ์เปลี่ยนหรือซ่อน นักพัฒนาสามารถควบคุมสิ่งนี้ได้ผ่านเมธอด UIResponder รวมถึงผ่าน inputView และ inputAccessoryView เพื่อแทนที่แป้นพิมพ์มาตรฐานด้วยแป้นพิมพ์ที่กำหนดเอง
Input Accessory View คือแผงพิเศษเพิ่มเติมเท่านั้นแป้นพิมพ์ที่เชื่อมโยงกับ first responder เช่น แผงที่มีปุ่ม ถัดไป ก่อนหน้า เสร็จสำเร็จสำหรับการนำทางระหว่างช่องป้อนข้อมูล แผงนี้จะปรากฏและซ่อนไปพร้อมกับแป้นพิมพ์ ซึ่งสังครโนยกับสถานะ first responder
| กิจกรรม | สถานะ first responder | แป้นพิมพ์ |
|---|---|---|
| แตะ UITextField | กลายเป็น first responder | ปรากฏ |
| กด Return | อยู่ต่อหรือ resign | อยู่ต่อหรือซ่อน |
| แตะช่องอื่น | ย้ายไปยังช่องใหม่ | เปลี่ยน |
| เรียก resignFirstResponder | ถูกลบ | ซ่อน |
| แอปพลิเคชันถูกซ่อน | เรียก resign โดยอัตโนมัติ | ซ่อน |
ResignFirstResponder คือเมธอด UIResponder ที่ลบสถานะ first responder ออกจากออบเจกต์ หลังจากการเรียก ออบเจกต์จะหยุดรับการสังเกตการใส่ และแป้นพิมพ์ (หากเปิดใช้งาน) จะซ่อน เมธอดจะคืนค่า Bool — true หาก resign สำเร็จ
นักพัฒนามักเรียก resignFirstResponder เพื่อตอบสนองต่อการกดปุ่ม เสร็จ การแตะบริเวณว่างของหน้าจอ (view.endEditing) หรือเมื่อออกจากหน้าจอ view.endEditing(true) เป็นวิธีที่สะดวกในการ resign สำหรับช่องข้อมูลย่อยทั้งหมดพร้อมกัน: มันจะเดินข้ามลำดับชั้นของ view ทั้งหมด และเรียก resignFirstResponder บน first responder ปัจจุบัน
// Resign เมื่อกดปุ่ม เสร็จ
@objc func doneButtonTapped() {
textField.resignFirstResponder()
}
// Resign เมื่อแตะบริเวณว่าง
override func touchesBegan(
_ touches: Set<UITouch>,
with event: UIEvent?
) {
view.endEditing(true)
}
// Resign สำหรับทุกช่องของฟอร์ม
func validateAndSubmit() {
view.endEditing(true)
// ตรรกะการส่งฟอร์ม
}
มีสถานการณ์ที่ resignFirstResponder อาจคืนค่า false ซึ่งเกิดขึ้นหากออบเจกต์ได้เขียนแทนเมธอดและห้ามการลบสถานะอย่างชัดเจน เช่น ช่องข้อมูลที่อยู่ระหว่างการตรวจสอบความถูกต้องอาจบล็อก resign ชั่วคราวเพื่อป้องกันการสูญเสียข้อมูล ในกรณีเช่นนี้ คุณต้องรอให้การตรวจสอบสำเร็จแล้วจึงบังคับให้ resign
UIResponder มีคุณสมบัติ isFirstResponder (อ่านอย่างเดียว) ซึ่งจะคืนค่า true หากออบเจกต์ที่กำหนดเป็น first responder อยู่ในขณะนั้น ทักษะนี้มีประโยชน์สำหรับตรรกะทางเงื่อนไข เช่น เพื่อหลีกเลี่ยงการดำเนินการหากช่องข้อมูลมีโฟกัสและผู้ใช้กำลังป้อนข้อมูล
iOS ไม่มี API ในตัวสำหรับการรับ first responder ปัจจุบัน ในระดับแอปพลิเคชัน นักพัฒนาสร้างความสามารถนี้โดยการเดินข้ามลำดับชั้นของ view โดยใช้เมธอด 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 หลัก และเรียก view.endEditing(true) ในตัวจัดการของมัน วิธีนี้จะค้นหา first responder ปัจจุบันโดยอัตโนมัติและเรียก resignFirstResponder หรือเขียนแทน touchesBegan ใน UIViewController ด้วยการเรียก endEditing
becomeFirstResponder จะคืนค่า false หาก canBecomeFirstResponder คืนค่า false มุมมองถูกซ่อน ไม่อยู่ในลำดับชั้นของหน้าต่างหรือ userInteractionEnabled = false รวมทั้งตรวจสอบว่ามุมมองถูกเพิ่มในหน้าต่างแล้ว — มุมมองที่ไม่ได้อยู่บนหน้าจอจะไม่ตอบสนองต่อ becomeFirstResponder
iOS ไม่มี API ทั่วไปสำหรับกรณนี้ ใช้การเดินข้ามโครงสร้าง view แบบเรียกซ้ำ โดยใช้ส่วนขยาย UIView ที่ตรวจสอบ isFirstResponder ในแต่ละ subview อีกทางเลือกคือเก็บ weak reference ไปยัง first responder ล่าสุดใน AppDelegate และอัพเดตโดยใช้ตัวแทน UITextField
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม