Gesture Recognizer — คืออะไร การจัดการสัมผัสใน iOS

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-02-27 เวลาอ่าน: 8 นาที
Gesture Recognizer คือสิ่งที่เป็นนามธรรมใน UIKit ที่แปลงลำดับการสัมผัสของผู้ใช้เป็นท่าทางที่รับรู้: แตะ ปัด กดค้าง หยิก หรือหมุน แทนที่จะติดตามพิกัดด้วยตนเองในเมธอด touchesBegan/touchesMoved นักพัฒนาเพิ่มออบเจ็กต์ UIGestureRecognizer ที่พร้อมใช้งานไปยัง UIView และใช้เมธอดการดำเนินการ ตามเอกสารสำหรับนักพัฒนาของ Apple UIGestureRecognizer รองรับคลาสย่อยในตัว 7 คลาสซึ่งครอบคลุม 95% ของท่าทางทั่วไปในแอปพลิเคชันมือถือ

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

  • UIGestureRecognizer คือคลาสนามธรรมของ UIKit สำหรับรับรู้รูปแบบการสัมผัส: การแตะ การปัด การหยิก การหมุน และการกดค้าง
  • คลาสย่อยในตัว 7 คลาส: UITapGestureRecognizer, UISwipeGestureRecognizer, UIPinchGestureRecognizer, UIRotationGestureRecognizer, UILongPressGestureRecognizer, UIPanGestureRecognizer, UIScreenEdgePanGestureRecognizer
  • ตัวรับรู้แต่ละตัวมีสถานะ (possible, began, changed, ended, cancelled, failed) ซึ่งอัปเดตเมื่อนิ้วเคลื่อนที่
  • เพื่อแก้ไขข้อขัดแย้งระหว่างท่าทาง ให้ใช้เมธอด require(toFail:) เพื่อกำหนดลำดับความสำคัญในการรับรู้
  • Gesture Recognizer ทำงานกับ UIKit และ UIViewRepresentable ใน SwiftUI แต่ SwiftUI ดั้งเดิมใช้ตัวปรับแต่งท่าทาง

Gesture Recognizer คืออะไร?

UIGestureRecognizer คือคลาสพื้นฐานนามธรรมใน UIKit ที่แยกกระบวนการรับรู้ท่าทางออกเป็นออบเจ็กต์แยกกัน แต่ละคลาสย่อยจัดการท่าทางหนึ่งประเภท: UITapGestureRecognizer จัดการการแตะด้วยจำนวนสัมผัสที่ระบุ UISwipeGestureRecognizer จัดการการปัดในทิศทางที่กำหนด นักพัฒนาเพิ่มตัวรับรู้ไปยัง UIView ผ่านเมธอด addGestureRecognizer(:) และ UIKit จะติดตามการสัมผัสโดยอัตโนมัติ อัปเดตสถานะ และเรียกใช้การดำเนินการเมื่อรับรู้

ก่อน UIGestureRecognizer (iOS 3.2, 2010) นักพัฒนาเขียนทับเมธอด UIResponder — touchesBegan, touchesMoved, touchesEnded — และวิเคราะห์เส้นทางการสัมผัสด้วยตนเอง สิ่งนี้นำไปสู่การทำซ้ำโค้ดและข้อผิดพลาดเมื่อจัดการกับการสัมผัสพร้อมกัน Apple ห่อหุ้มตรรกะนี้ใน UIGestureRecognizer เพิ่มการรองรับการสัมผัสหลายจุด การยกเลิกท่าทาง และการทำงานพร้อมกันของตัวรับรู้หลายตัวบนวิวเดียวกัน

ตามเซสชัน WWDC Gesture Recognizer จัดการการสัมผัสพร้อมกันสูงสุด 11 จุด บน iPad และ 5 จุดบน iPhone ที่ IT Sectr เราใช้ UIGestureRecognizer เป็นวิธีมาตรฐานในการจัดการอินพุตของผู้ใช้ในทุกโปรเจกต์ UIKit — ซึ่งช่วยกำจัดบักที่เกี่ยวข้องกับการติดตาม touchesBegan ด้วยตนเอง

สถานะของ UIGestureRecognizer

UIGestureRecognizer แต่ละตัวผ่าน 7 สถานะที่เป็นไปได้ ซึ่งกำหนดใน enum UIGestureRecognizer.State สถานะเหล่านี้สะท้อนวงจรชีวิตของการรับรู้: จากการตรวจจับการสัมผัสไปจนถึงการเสร็จสมบูรณ์หรือการยกเลิก การทำความเข้าใจสถานะเป็นสิ่งสำคัญสำหรับการใช้งานตัวรับรู้แบบกำหนดเองและการดีบักข้อขัดแย้ง

สถานะ ความหมาย เมื่อเกิดขึ้น
.possible สถานะเริ่มต้น ยังไม่รับรู้ท่าทาง ทันทีหลังจากเพิ่มไปยังวิว
.began รับรู้ท่าทางและเริ่มดำเนินการ เมื่อนิ้วเคลื่อนที่ครั้งแรกสำหรับ pan/longPress
.changed พารามิเตอร์ของท่าทางเปลี่ยนไป (พิกัด, มุม) ทุกครั้งที่นิ้วเคลื่อนที่
.ended ผู้ใช้ยกนิ้วขึ้น ท่าทางเสร็จสมบูรณ์ ที่ touchesEnded
.cancelled ท่าทางถูกขัดจังหวะโดยระบบ (สายเรียกเข้า, การเปลี่ยนทิศทาง) ที่ touchesCancelled
.failed ไม่รับรู้ท่าทางตามเงื่อนไข ที่ touchesCancelled โดยไม่มีการรับรู้
.recognized คำพ้องของ .ended; รับรู้ท่าทางสำเร็จ เหมือน .ended

ท่าทางไม่ต่อเนื่อง (tap, swipe) เปลี่ยนจาก .possible ไปยัง .ended หรือ .failed โดยตรง ท่าทางต่อเนื่อง (pan, pinch, rotation, longPress) ผ่าน .possible → .began → .changed (ซ้ำ) → .ended ในเมธอดการดำเนินการ ให้ตรวจสอบ gestureRecognizer.state — ซึ่งช่วยแยกแยะจุดเริ่มต้น การเปลี่ยนแปลง และจุดสิ้นสุดของท่าทาง

ประเภทของท่าทางใน iOS

UIKit มีคลาสย่อย UIGestureRecognizer ในตัว 7 คลาส ครอบคลุมสถานการณ์การโต้ตอบส่วนใหญ่ แต่ละคลาสย่อยมีการตั้งค่าเฉพาะ: numberOfTapsRequired สำหรับการแตะ direction สำหรับการปัด minimumPressDuration สำหรับการกดค้าง

  • UITapGestureRecognizer — รับรู้การแตะเดี่ยวและหลายครั้ง กำหนดค่าจำนวนการแตะ (numberOfTapsRequired) และจำนวนนิ้ว (numberOfTouchesRequired) ได้ ใช้สำหรับปุ่ม ลิงก์ การเลือกองค์ประกอบ
  • UISwipeGestureRecognizer — รับรู้การปัดในหนึ่งในสี่ทิศทาง (right, left, up, down) คุณสมบัติ direction กำหนดทิศทาง; numberOfTouchesRequired กำหนดจำนวนนิ้ว
  • UIPanGestureRecognizer — ท่าทางต่อเนื่องสำหรับการลาก เมธอด translation(in:) คืนค่าการกระจัดจากจุดเริ่มต้น ใช้สำหรับลากและวาง แถบเลื่อน ดึงเพื่อรีเฟรช
  • UIPinchGestureRecognizer — การซูมด้วยสองนิ้ว คุณสมบัติ scale สะท้อนปัจจัยสเกลปัจจุบัน อธิบายโดยละเอียดในบทความ Pinch-to-Zoom
  • UIRotationGestureRecognizer — การหมุนด้วยสองนิ้ว คุณสมบัติ rotation เก็บมุมในหน่วยเรเดียน ใช้สำหรับหมุนภาพ แผนที่ แคนวาส
  • UILongPressGestureRecognizer — การกดค้าง พารามิเตอร์: minimumPressDuration (วินาที), allowableMovement (พิกเซล) ใช้สำหรับเมนูบริบท การลากองค์ประกอบ
  • UIScreenEdgePanGestureRecognizer — การปัดจากขอบหน้าจอ คุณสมบัติ edges ระบุว่าขอบใดที่จะติดตาม ใช้สำหรับท่าทางนำทาง แผงการแจ้งเตือน

สำหรับท่าทางแบบกำหนดเอง (เช่น การวาดซิกแซก) ให้สร้างคลาสย่อยของ UIGestureRecognizer โดยเขียนทับ touchesBegan, touchesMoved, touchesEnded และอัปเดตสถานะ Apple แนะนำให้ใช้คลาสในตัวเมื่อเป็นไปได้ — คลาสเหล่านี้ได้รับการปรับให้เหมาะสมและโต้ตอบกันอย่างถูกต้อง

การแก้ไขข้อขัดแย้งระหว่างท่าทาง

เมื่อใช้ UIGestureRecognizer หลายตัวบน UIView เดียวกัน (เช่น การแตะและการแตะสองครั้ง) จะเกิดข้อขัดแย้งในการรับรู้: เมื่อแตะสองครั้ง การแตะเดี่ยวจะทำงานก่อน Apple มีเมธอด require(toFail:) เพื่อหน่วงเวลาการรับรู้ท่าทางหนึ่งจนกว่าอีกท่าทางจะล้มเหลว

กลไกทำงานดังนี้: โดยการเรียก tapRecognizer.require(toFail: doubleTapRecognizer) คุณระบุว่า tapRecognizer จะเปลี่ยนเป็นสถานะ .recognized ต่อเมื่อ doubleTapRecognizer สิ้นสุดใน .failed เท่านั้น สิ่งนี้เพิ่มความล่าช้า ~0.3 วินาทีก่อนดำเนินการแตะเดี่ยว — ผู้ใช้แตะสองครั้งและการแตะครั้งแรกจะถูกข้ามไป วิธีทางเลือกคือตัวแทน UIGestureRecognizerDelegate ที่มีเมธอด gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) ซึ่งอนุญาตให้รับรู้พร้อมกัน (เช่น pan + pinch สำหรับแผนที่)

ตาม WWDC 2020 ประมาณ 15% ของบัก ในแอปพลิเคชัน UIKit เกี่ยวข้องกับการกำหนดค่าขัดแย้งของท่าทางที่ไม่ถูกต้อง ที่ IT Sectr เรามาตรฐานวิธีการ: แต่ละหน้าจอมีแผนผังท่าทางที่มีลำดับความสำคัญ require(toFail:) — ซึ่งกำจัดบักการทำงานซ้ำของการแตะโดยสมบูรณ์

ตัวอย่างโค้ด Swift

ตัวอย่างที่ 1: UITapGestureRecognizer — แตะที่รูปภาพ

เพิ่มตัวจัดการการแตะเดี่ยวไปยัง UIImageView เมื่อแตะ ความโปร่งใสของรูปภาพจะเปลี่ยนไป — ตัวอย่างง่าย ๆ ที่แสดงการผูกท่าทางกับวิว

swift
import UIKit

class ImageViewController: UIViewController {

    @IBOutlet private var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        let tap = UITapGestureRecognizer(
            target: self,
            action: #selector(handleTap(_:))
        )
        tap.numberOfTapsRequired = 1
        imageView.addGestureRecognizer(tap)
        imageView.isUserInteractionEnabled = true
    }

    @objc private func handleTap(_: UITapGestureRecognizer) {
        UIView.animate(withDuration: 0.2) {
            self.imageView.alpha = self.imageView.alpha == 1.0 ? 0.5 : 1.0
        }
    }
}

จุดสำคัญ: isUserInteractionEnabled บน UIImageView มีค่าเป็น false โดยค่าเริ่มต้น — หากไม่มีแฟล็กนี้ Gesture Recognizer จะไม่ได้รับการสัมผัส สำหรับ UIView และ UIButton แฟล็กนี้เปิดใช้งานโดยค่าเริ่มต้น เมธอดการดำเนินการรับพารามิเตอร์ UITapGestureRecognizer ซึ่งสามารถใช้ location(in:) เพื่อกำหนดพิกัดของการแตะ

ตัวอย่างที่ 2: UISwipeGestureRecognizer — ปัดเพื่อนำทาง

ใช้การปัดซ้ายเพื่อกลับไปยังหน้าจอก่อนหน้า สาธิตการกำหนดทิศทางและการผูกท่าทางกับวิวรากของคอนโทรลเลอร์

swift
import UIKit

class DetailViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let swipeLeft = UISwipeGestureRecognizer(
            target: self,
            action: #selector(handleSwipe(_:))
        )
        swipeLeft.direction = .left
        view.addGestureRecognizer(swipeLeft)
    }

    @objc private func handleSwipe(_: UISwipeGestureRecognizer) {
        navigationController?.popViewController(animated: true)
    }
}

UISwipeGestureRecognizer เป็นท่าทางไม่ต่อเนื่อง: มันเปลี่ยนเป็น .recognized ทันทีหลังจากการรับรู้ โดยไม่มีสถานะ .changed ระหว่างกลาง ดังนั้นจึงไม่จำเป็นต้องตรวจสอบสถานะในการดำเนินการ — ท่าทางจะรับรู้ (การดำเนินการทำงาน) หรือไม่ก็ตาม คุณสมบัติ direction รับหนึ่งในสี่ค่า: .left, .right, .up, .down เพื่อรองรับหลายทิศทาง ให้สร้างตัวรับรู้แยกกันสำหรับแต่ละทิศทาง

ตัวอย่างที่ 3: การรวมท่าทางด้วย require(toFail:)

แสดงวิธีกำหนดค่าการแตะเดี่ยวและการแตะสองครั้งบนวิวเดียวกันโดยไม่ขัดแย้ง ตัวรับรู้การแตะสองครั้งมีลำดับความสำคัญ — การแตะเดี่ยวจะทำงานก็ต่อเมื่อไม่รับรู้การแตะสองครั้ง

swift
import UIKit

class TapViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let singleTap = UITapGestureRecognizer(
            target: self,
            action: #selector(handleSingleTap)
        )
        singleTap.numberOfTapsRequired = 1

        let doubleTap = UITapGestureRecognizer(
            target: self,
            action: #selector(handleDoubleTap)
        )
        doubleTap.numberOfTapsRequired = 2

        singleTap.require(toFail: doubleTap)

        view.addGestureRecognizer(singleTap)
        view.addGestureRecognizer(doubleTap)
    }

    @objc private func handleSingleTap() {
        print("Single tap — after 0.3s delay")
    }

    @objc private func handleDoubleTap() {
        print("Double tap — instant")
    }
}

หากไม่มี require(toFail:) เมื่อแตะสองครั้ง handleSingleTap จะทำงานก่อน แล้วตามด้วย handleDoubleTap — ซึ่งทำให้ UX เสียหาย เมื่อมี require(toFail:) การแตะเดี่ยวจะรอ ~0.3 วินาทีเพื่อให้แน่ใจว่าไม่มีการแตะครั้งที่สองตามมา ที่ IT Sectr รูปแบบนี้ใช้ในโปรแกรมแก้ไขรูปภาพและแกลเลอรี โดยการแตะสองครั้งจะซูมและการแตะเดี่ยวจะเลือกองค์ประกอบ

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

สามารถใช้ Gesture Recognizer หลายตัวบนวิวเดียวกันได้หรือไม่?

ได้ UIView รองรับอินสแตนซ์ UIGestureRecognizer หลายตัวพร้อมกัน เพื่อแก้ไขข้อขัดแย้ง ให้ใช้เมธอด require(toFail:) ซึ่งกำหนดลำดับการรับรู้ สำหรับการทำงานท่าทางแบบขนาน (เช่น pan + pinch บนแผนที่) ให้ใช้เมธอดตัวแทน gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) ที่คืนค่า true

UIGestureRecognizer แตกต่างจาก touchesBegan อย่างไร?

UIGestureRecognizer เป็นสิ่งที่เป็นนามธรรมระดับสูงที่รับรู้รูปแบบการสัมผัสโดยอัตโนมัติและจัดการสถานะ touchesBegan เป็นเมธอดระดับต่ำของ UIResponder ที่ต้องการการติดตามพิกัด การจับเวลา และการยกเลิกการสัมผัสด้วยตนเอง Gesture Recognizer ง่ายกว่า เชื่อถือได้มากกว่า และเหมาะสำหรับท่าทางมาตรฐาน touchesBegan เหมาะสมสำหรับกราฟิกที่กำหนดเองเท่านั้น

Gesture Recognizer ทำงานใน SwiftUI หรือไม่?

SwiftUI ดั้งเดิมใช้ตัวปรับแต่ง: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture สิ่งเหล่านี้เป็นอะนาล็อกเชิงประกาศของ UIGestureRecognizer ที่รวมอยู่ในลำดับชั้นของ SwiftUI หากจำเป็น สามารถห่อตัวรับรู้ UIKit ผ่าน UIViewRepresentable ได้ แต่ Apple แนะนำให้ใช้ท่าทาง SwiftUI ดั้งเดิม

สรุป

  • UIGestureRecognizer คือสิ่งที่เป็นนามธรรมของ UIKit สำหรับแยกตรรกะการรับรู้ท่าทางออกเป็นออบเจ็กต์แยกกันพร้อมการจัดการสถานะอัตโนมัติ
  • คลาสย่อยในตัว 7 คลาสครอบคลุม 95% ของท่าทางทั่วไป: แตะ ปัด เลื่อน หยิก หมุน กดค้าง และปัดจากขอบ
  • ตัวรับรู้แต่ละตัวผ่าน 7 สถานะ — จาก .possible ถึง .ended/.failed ทำให้สามารถติดตามท่าทางไม่ต่อเนื่องและต่อเนื่องได้อย่างแม่นยำ
  • เมธอด require(toFail:) แก้ไขข้อขัดแย้งระหว่างท่าทางบนวิวเดียวกันโดยกำหนดลำดับความสำคัญในการรับรู้
  • SwiftUI ใช้ตัวปรับแต่งท่าทางเชิงประกาศ แต่ตัวรับรู้ UIKit พร้อมใช้งานผ่าน UIViewRepresentable
  • Gesture Recognizer จำเป็นสำหรับโปรเจกต์ UIKit; touchesBegan เหมาะสมสำหรับการวาดแบบกำหนดเองและกราฟิกระดับต่ำเท่านั้น
  • ใช้ require(toFail:) สำหรับคู่แตะ/แตะสองครั้ง และ gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) สำหรับท่าทางขนาน

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

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

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

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