Gesture Recognizer — apa itu, penanganan sentuhan di iOS

Penulis: IT Sectr Diterbitkan: 2026-02-27 Waktu membaca: 8 mnt
Gesture Recognizer — abstraksi di UIKit yang mengubah urutan sentuhan pengguna menjadi gestur yang dikenali: tap, geser, tekan lama, cubit, atau putar. Alih-alih melacak koordinat secara manual di metode touchesBegan/touchesMoved, pengembang menambahkan objek UIGestureRecognizer siap pakai ke UIView dan mengimplementasikan metode aksi. Menurut Apple Developer Documentation, UIGestureRecognizer mendukung 7 subkelas bawaan yang mencakup 95% gestur umum di aplikasi seluler.

Poin utama

  • UIGestureRecognizer — kelas abstrak UIKit untuk mengenali pola sentuhan: tap, geser, cubitan, putaran, dan tekan lama.
  • 7 subkelas bawaan: UITapGestureRecognizer, UISwipeGestureRecognizer, UIPinchGestureRecognizer, UIRotationGestureRecognizer, UILongPressGestureRecognizer, UIPanGestureRecognizer, UIScreenEdgePanGestureRecognizer.
  • Setiap pengenal memiliki status (possible, began, changed, ended, cancelled, failed) yang diperbarui seiring pergerakan jari.
  • Untuk menyelesaikan konflik antar gestur, digunakan metode require(toFail:), yang menetapkan prioritas pengenalan.
  • Gesture Recognizer bekerja dengan UIKit dan UIViewRepresentable di SwiftUI, tetapi di SwiftUI asli digunakan pengubah gestur.

Apa itu Gesture Recognizer?

UIGestureRecognizer — kelas dasar abstrak di UIKit yang mendekomposisi proses pengenalan gestur menjadi objek terpisah. Setiap subkelas bertanggung jawab untuk satu jenis gestur: UITapGestureRecognizer — untuk tap dengan jumlah jari tertentu, UISwipeGestureRecognizer — untuk geser ke arah tertentu. Pengembang menambahkan pengenal ke UIView melalui metode addGestureRecognizer(:), dan UIKit secara otomatis melacak sentuhan, memperbarui status, dan memanggil aksi saat dikenali.

Sebelum munculnya UIGestureRecognizer (iOS 3.2, 2010), pengembang menimpa metode UIResponder — touchesBegan, touchesMoved, touchesEnded — dan menganalisis lintasan sentuhan secara manual. Ini menyebabkan duplikasi kode dan kesalahan dalam menangani sentuhan simultan. Apple mengenkapsulasi logika ini ke dalam UIGestureRecognizer, menambahkan dukungan untuk multitouch, pembatalan gestur, dan kerja simultan beberapa pengenal pada satu tampilan.

Menurut sesi WWDC, Gesture Recognizer memproses hingga 11 sentuhan simultan di iPad dan 5 di iPhone. Di IT Sectr, kami menggunakan UIGestureRecognizer sebagai cara standar untuk menangani masukan pengguna di semua proyek UIKit — ini menghilangkan bug terkait pelacakan manual touchesBegan.

Status UIGestureRecognizer

Setiap UIGestureRecognizer melalui 7 status yang mungkin, didefinisikan dalam enum UIGestureRecognizer.State. Status ini mencerminkan siklus hidup pengenalan: dari deteksi sentuhan hingga penyelesaian atau pembatalan gestur. Memahami status sangat penting untuk mengimplementasikan pengenal kustom dan men-debug konflik.

Status Arti Kapan terjadi
.possible Status awal, gestur belum dikenali Segera setelah ditambahkan ke tampilan
.began Gestur dikenali dan mulai dijalankan Pada gerakan jari pertama untuk pan/longPress
.changed Parameter gestur berubah (koordinat, sudut) Pada setiap gerakan jari
.ended Pengguna mengangkat jari, gestur selesai Saat touchesEnded
.cancelled Gestur diinterupsi oleh sistem (panggilan masuk, perubahan orientasi) Saat touchesCancelled
.failed Gestur tidak dikenali sesuai kondisi Saat touchesCancelled tanpa pengenalan
.recognized Sinonim untuk .ended; gestur berhasil dikenali Sama seperti .ended

Gestur diskrit (tap, swipe) beralih dari .possible langsung ke .ended atau .failed. Gestur kontinu (pan, pinch, rotation, longPress) melalui .possible → .began → .changed (berulang) → .ended. Di metode aksi, periksa gestureRecognizer.state — ini memungkinkan membedakan awal, perubahan, dan akhir gestur.

Jenis gestur di iOS

UIKit menyediakan 7 subkelas bawaan UIGestureRecognizer, yang mencakup sebagian besar skenario interaksi. Setiap subkelas memiliki pengaturan khusus: numberOfTapsRequired untuk tap, direction untuk geser, minimumPressDuration untuk tekan lama.

  • UITapGestureRecognizer — mengenali tap tunggal dan ganda. Jumlah sentuhan (numberOfTapsRequired) dan jari (numberOfTouchesRequired) dapat dikonfigurasi. Digunakan untuk tombol, tautan, pemilihan elemen.
  • UISwipeGestureRecognizer — mengenali geser ke salah satu dari empat arah (right, left, up, down). Properti direction menentukan arah; numberOfTouchesRequired — jumlah jari.
  • UIPanGestureRecognizer — gestur kontinu untuk menyeret. Metode translation(in:) mengembalikan perpindahan dari titik awal. Digunakan untuk drag-and-drop, karusel, pull-to-refresh.
  • UIPinchGestureRecognizer — penskalaan dengan dua jari. Properti scale mencerminkan faktor skala saat ini. Dibahas secara rinci di artikel Pinch-to-Zoom.
  • UIRotationGestureRecognizer — rotasi dengan dua jari. Properti rotation menyimpan sudut dalam radian. Digunakan untuk memutar gambar, peta, kanvas.
  • UILongPressGestureRecognizer — tekan lama. Parameter minimumPressDuration (detik), allowableMovement (piksel). Digunakan untuk menu konteks, menyeret elemen.
  • UIScreenEdgePanGestureRecognizer — pan dari tepi layar. Properti edges menentukan tepi mana yang dilacak. Digunakan untuk gestur navigasi, tirai notifikasi.

Untuk gestur kustom (misalnya, menggambar zigzag), dibuat subkelas UIGestureRecognizer dengan menimpa metode touchesBegan, touchesMoved, touchesEnded dan memperbarui status. Apple merekomendasikan penggunaan kelas bawaan jika memungkinkan — kelas tersebut dioptimalkan dan berinteraksi dengan benar satu sama lain.

Menyelesaikan konflik antar gestur

Ketika beberapa UIGestureRecognizer digunakan pada satu UIView (misalnya, tap dan double-tap), terjadi konflik pengenalan: pada tap ganda, tap tunggal terpicu terlebih dahulu. Untuk solusinya, Apple menyediakan metode require(toFail:), yang menunda pengenalan satu gestur sampai gestur lainnya gagal.

Mekanismenya bekerja sebagai berikut: dengan memanggil tapRecognizer.require(toFail: doubleTapRecognizer), Anda menentukan bahwa tapRecogniser akan beralih ke status .recognized hanya setelah doubleTapRecogniser selesai dalam .failed. Ini menambahkan penundaan ~0,3 detik sebelum eksekusi tap tunggal — pengguna mengetuk dua kali, dan tap pertama diabaikan. Metode alternatif — delegasi UIGestureRecognizerDelegate dengan metode gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:), yang mengizinkan pengenalan simultan (misalnya, pan + pinch untuk peta).

Menurut WWDC 2020, sekitar 15% bug di aplikasi UIKit terkait dengan konfigurasi konflik gestur yang salah. Di IT Sectr, kami menstandarisasi pendekatan: untuk setiap layar, dibuat skema gestur dengan prioritas require(toFail:) — ini sepenuhnya menghilangkan bug dengan pemicuan ganda tap.

Contoh kode di Swift

Contoh 1: UITapGestureRecognizer — tap pada gambar

Menambahkan handler tap tunggal pada UIImageView. Saat diketuk, gambar mengubah transparansi — contoh paling sederhana yang menunjukkan pengikatan gestur ke tampilan.

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

Poin penting: isUserInteractionEnabled di UIImageView secara default adalah false — tanpa bendera ini, Gesture Recognizer tidak akan menerima sentuhan. Untuk UIView dan UIButton, bendera ini aktif secara default. Metode aksi menerima parameter UITapGestureRecognizer yang melaluinya location(in:) dapat diperoleh untuk menentukan koordinat tap.

Contoh 2: UISwipeGestureRecognizer — geser untuk navigasi

Mengimplementasikan geser ke kiri untuk kembali ke layar sebelumnya. Mendemonstrasikan konfigurasi arah dan pengikatan gestur ke tampilan root controller.

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 — gestur diskrit: ia beralih ke .recognised segera setelah dikenali, tanpa .changed perantara. Oleh karena itu, di aksi, status tidak perlu diperiksa — gestur dikenali (aksi dipanggil) atau tidak. Properti direction menerima salah satu dari empat nilai: .left, .right, .up, .down. Untuk mendukung beberapa arah, buat pengenal terpisah untuk setiap arah.

Contoh 3: Kombinasi gestur dengan require(toFail:)

Menunjukkan cara mengonfigurasi tap tunggal dan ganda pada tampilan yang sama tanpa konflik. Pengenal tap ganda memiliki prioritas — tap tunggal hanya terpicu jika tap ganda tidak dikenali.

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

Tanpa require(toFail:), pada tap ganda, handleSingleTap akan dipanggil terlebih dahulu, lalu handleDoubleTap — ini merusak UX. Dengan require(toFail:), tap tunggal menunggu ~0,3 detik untuk memastikan tap kedua tidak menyusul. Di IT Sectr, pola ini digunakan di editor gambar dan galeri, di mana tap ganda memperbesar, dan tap tunggal memilih elemen.

Pertanyaan yang sering diajukan

Bisakah beberapa Gesture Recognizer digunakan pada satu tampilan?

Ya, UIView mendukung beberapa UIGestureRecognizer secara simultan. Untuk menyelesaikan konflik, gunakan metode require(toFail:), yang menentukan urutan pengenalan. Untuk kerja paralel gestur (misalnya, pan + pinch pada peta), implementasikan delegasi gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:), yang mengembalikan true.

Apa perbedaan UIGestureRecognizer dengan touchesBegan?

UIGestureRecognizer — abstraksi tingkat tinggi yang secara otomatis mengenali pola sentuhan dan mengelola status. touchesBegan — metode tingkat rendah UIResponder yang memerlukan pelacakan manual koordinat, waktu, dan pembatalan sentuhan. Gesture Recognizer lebih sederhana, lebih andal, dan lebih disukai untuk gestur standar; touchesBagan hanya dibenarkan untuk grafik kustom.

Apakah Gesture Recognizer berfungsi di SwiftUI?

Di SwiftUI asli, digunakan pengubah: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture. Ini adalah padanan deklaratif dari UIGestureRecognizer, terintegrasi ke dalam hierarki SwiftUI. Jika perlu, Anda dapat membungkus pengenal UIKit melalui UIViewRepresentable, tetapi Apple merekomendasikan penggunaan gestur asli SwiftUI.

Ringkasan

  • UIGestureRecognizer — abstraksi UIKit untuk mendekomposisi logika pengenalan gestur menjadi objek terpisah dengan manajemen status otomatis.
  • 7 subkelas bawaan mencakup 95% gestur umum: tap, geser, pan, cubit, putar, tekan lama, dan geser dari tepi.
  • Setiap pengenal melalui 7 status — dari .possible hingga .ended/.failed, memungkinkan pelacakan tepat gestur diskrit dan kontinu.
  • Metode require(toFail:) menyelesaikan konflik antar gestur pada tampilan yang sama, menetapkan prioritas pengenalan.
  • Di SwiftUI, digunakan pengubah gestur deklaratif, tetapi pengenal UIKit dapat diakses melalui UIViewRepresentable.
  • Gesture Recognizer wajib untuk proyek UIKit; touchesBagan hanya dibenarkan untuk gambar kustom dan grafik tingkat rendah.
  • Gunakan require(toFail:) untuk pasangan tap/double-tap dan gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) untuk gestur paralel.

Kami akan mengembangkan aplikasi seluler turnkey

IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.

Diskusikan proyek

Baca juga