Gesture Recognizer — ce este, gestionarea atingerilor în iOS

Autor: IT Sectr Publicat: 2026-02-27 Timp de citire: 8 min
Gesture Recognizer — o abstractizare în UIKit care transformă o secvență de atingeri ale utilizatorului într-un gest recunoscut: tap, glisare, apăsare lungă, ciupire sau rotire. În loc să urmăriți manual coordonatele în metodele touchesBegan/touchesMoved, dezvoltatorul adaugă un obiect UIGestureRecognizer gata făcut pe UIView și implementează metoda action. Potrivit Apple Developer Documentation, UIGestureRecognizer suportă 7 subclase încorporate care acoperă 95% din gesturile tipice în aplicațiile mobile.

Principalele puncte

  • UIGestureRecognizer — clasa abstractă UIKit pentru recunoașterea modelelor de atingeri: tapuri, glisări, ciupiri, rotiri și apăsări lungi.
  • 7 subclase încorporate: UITapGestureRecognizer, UISwipeGestureRecognizer, UIPinchGestureRecognizer, UIRotationGestureRecognizer, UILongPressGestureRecognizer, UIPanGestureRecognizer, UIScreenEdgePanGestureRecognizer.
  • Fiecare recunoscător are o stare (possible, began, changed, ended, cancelled, failed) care se actualizează pe măsură ce degetele se mișcă.
  • Pentru rezolvarea conflictelor între gesturi se folosește metoda require(toFail:), care stabilește prioritatea recunoașterii.
  • Gesture Recognizer funcționează cu UIKit și UIViewRepresentable în SwiftUI, dar în SwiftUI nativ se aplică modificatori de gesturi.

Ce este Gesture Recognizer?

UIGestureRecognizer — o clasă de bază abstractă în UIKit care descompune procesul de recunoaștere a gesturilor în obiecte separate. Fiecare subclasă răspunde pentru un tip de gest: UITapGestureRecognizer — pentru tap cu un număr specific de degete, UISwipeGestureRecognizer — pentru glisarea într-o direcție dată. Dezvoltatorul adaugă recunoscătorul pe UIView prin metoda addGestureRecognizer(:), iar UIKit urmărește automat atingerile, actualizează starea și apelează acțiunea la recunoaștere.

Înainte de apariția UIGestureRecognizer (iOS 3.2, 2010), dezvoltatorii suprascriau metodele UIResponder — touchesBegan, touchesMoved, touchesEnded — și analizau manual traiectoria atingerilor. Aceasta ducea la duplicarea codului și erori la procesarea atingerilor simultane. Apple a încapsulat această logică în UIGestureRecognizer, adăugând suport pentru multitouch, anularea gesturilor și funcționarea simultană a mai multor recunoscători pe aceeași vizualizare.

Conform sesiunilor WWDC, Gesture Recognizer procesează până la 11 atingeri simultane pe iPad și 5 pe iPhone. În IT Sectr folosim UIGestureRecognizer ca metodă standard de procesare a intrărilor utilizatorului în toate proiectele UIKit — aceasta a eliminat bug-urile legate de urmărirea manuală a touchesBegan.

Stările UIGestureRecognizer

Fiecare UIGestureRecognizer trece prin 7 stări posibile, definite în enum-ul UIGestureRecognizer.State. Aceste stări reflectă ciclul de viață al recunoașterii: de la detectarea atingerii până la finalizarea sau anularea gestului. Înțelegerea stărilor este critică pentru implementarea recunoscătorilor personalizați și depanarea conflictelor.

Stare Semnificație Când apare
.possible Stare inițială, gestul nu a fost încă recunoscut Imediat după adăugarea pe vizualizare
.began Gestul a fost recunoscut și a început să se execute La prima mișcare a degetului pentru pan/longPress
.changed Parametrii gestului s-au schimbat (coordonate, unghi) La fiecare mișcare a degetului
.ended Utilizatorul a ridicat degetul, gestul s-a încheiat La touchesEnded
.cancelled Gestul a fost întrerupt de sistem (apel primit, schimbare orientare) La touchesCancelled
.failed Gestul nu a fost recunoscut conform condițiilor La touchesCancelled fără recunoaștere
.recognized Sinonim pentru .ended; gestul a fost recunoscut cu succes La fel ca .ended

Gesturile discrete (tap, swipe) trec din .possible direct în .ended sau .failed. Gesturile continue (pan, pinch, rotation, longPress) trec prin .possible → .began → .changed (de mai multe ori) → .ended. În metoda action, verificați gestureRecognizer.state — acest lucru permite diferențierea începutului, modificării și sfârșitului gestului.

Tipuri de gesturi în iOS

UIKit oferă 7 subclase încorporate ale UIGestureRecognizer, care acoperă majoritatea scenariilor de interacțiune. Fiecare subclasă are setări specifice: numberOfTapsRequired pentru tap, direction pentru glisare, minimumPressDuration pentru apăsare lungă.

  • UITapGestureRecognizer — recunoaște tapurile simple și multiple. Se configurează numărul de atingeri (numberOfTapsRequired) și de degete (numberOfTouchesRequired). Folosit pentru butoane, linkuri, selectarea elementelor.
  • UISwipeGestureRecognizer — recunoaște glisarea într-una din cele patru direcții (right, left, up, down). Proprietatea direction setează direcția; numberOfTouchesRequired — numărul de degete.
  • UIPanGestureRecognizer — gest continuu pentru tragere. Metoda translation(in:) returnează deplasarea față de punctul de pornire. Folosit pentru drag-and-drop, carusele, pull-to-refresh.
  • UIPinchGestureRecognizer — scalare cu două degete. Proprietatea scale reflectă factorul de scalare curent. Analizat în detaliu în articolul Pinch-to-Zoom.
  • UIRotationGestureRecognizer — rotire cu două degete. Proprietatea rotation stochează unghiul în radiani. Folosit pentru rotirea imaginilor, hărților, canvasurilor.
  • UILongPressGestureRecognizer — apăsare lungă. Parametrii minimumPressDuration (secunde), allowableMovement (pixeli). Folosit pentru meniuri contextuale, tragerea elementelor.
  • UIScreenEdgePanGestureRecognizer — panoramare de la marginea ecranului. Proprietatea edges specifică ce margine să urmărească. Folosit pentru gesturi de navigare, perdele de notificări.

Pentru gesturi personalizate (de exemplu, desenarea unui zigzag) se creează o subclasă a UIGestureRecognizer cu suprascrierea metodelor touchesBegan, touchesMoved, touchesEnded și actualizarea stării. Apple recomandă utilizarea claselor încorporate acolo unde este posibil — sunt optimizate și interacționează corect între ele.

Rezolvarea conflictelor între gesturi

Când pe aceeași UIView sunt utilizate mai multe UIGestureRecognizer (de exemplu, tap și double-tap), apare un conflict de recunoaștere: la dublu tap, mai întâi se declanșează tapul simplu. Pentru rezolvare, Apple oferă metoda require(toFail:), care întârzie recunoașterea unui gest până când celălalt se termină cu eșec.

Mecanismul funcționează astfel: apelând tapRecognizer.require(toFail: doubleTapRecognizer), specificați că tapRecogniser va trece în starea .recognized numai după ce doubleTapRecogniser se termină în .failed. Aceasta adaugă o întârziere de ~0.3 secunde înainte de executarea tapului simplu — utilizatorul atinge de două ori, iar primul tap este ignorat. Metoda alternativă — delegatul UIGestureRecognizerDelegate cu metoda gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:), care permite recunoașterea simultană (de exemplu, pan + pinch pentru hartă).

Potrivit WWDC 2020, aproximativ 15% din bug-uri în aplicațiile UIKit sunt legate de configurarea incorectă a conflictelor de gesturi. În IT Sectr am standardizat abordarea: pentru fiecare ecran se creează o schemă de gesturi cu prioritățile require(toFail:) — aceasta a eliminat complet bug-urile cu declanșarea dublă a tapurilor.

Exemple de cod în Swift

Exemplul 1: UITapGestureRecognizer — tap pe imagine

Adaugă un handler de tap simplu pe UIImageView. La tap, imaginea își schimbă transparența — exemplul cel mai simplu care arată atașarea unui gest la o vizualizare.

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

Momentul cheie: isUserInteractionEnabled pe UIImageView este implicit false — fără această flag, Gesture Recognizer nu va primi atingeri. Pentru UIView și UIButton flag-ul este activat implicit. Metoda action primește un parametru UITapGestureRecognizer prin care se poate obține location(in:) pentru determinarea coordonatelor tapului.

Exemplul 2: UISwipeGestureRecognizer — glisare pentru navigare

Implementează glisarea la stânga pentru revenirea la ecranul anterior. Demonstrează configurarea direcției și atașarea gestului la vizualizarea rădăcină a controlerului.

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 — un gest discret: trece în .recognised imediat după recunoaștere, fără .changed intermediar. Prin urmare, în action nu trebuie verificată starea — gestul este fie recunoscut (se apelează acțiunea), fie nu. Proprietatea direction acceptă una dintre cele patru valori: .left, .right, .up, .down. Pentru a suporta mai multe direcții, creați recunoscători separați pentru fiecare.

Exemplul 3: Combinația de gesturi cu require(toFail:)

Arată cum să configurați tapul simplu și dublu pe aceeași vizualizare fără conflict. Recunoscătorul de tap dublu are prioritate — tapul simplu se declanșează numai dacă tapul dublu nu a fost recunoscut.

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

Fără require(toFail:) la tapul dublu, mai întâi se va apela handleSingleTap, apoi handleDoubleTap — acest lucru strică UX-ul. Cu require(toFail:) tapul simplu așteaptă ~0.3 secunde pentru a se asigura că al doilea tap nu urmează. În IT Sectr acest model este folosit în editoarele de imagini și galerii, unde tapul dublu mărește, iar cel simplu — selectează un element.

Întrebări frecvente

Se pot folosi mai multe Gesture Recognizer pe aceeași vizualizare?

Da, UIView suportă mai multe UIGestureRecognizer simultan. Pentru rezolvarea conflictelor, folosiți metoda require(toFail:), care stabilește ordinea de recunoaștere. Pentru funcționarea paralelă a gesturilor (de exemplu, pan + pinch pe o hartă) implementați delegatul gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:), care returnează true.

Cu ce se diferențiază UIGestureRecognizer de touchesBegan?

UIGestureRecognizer — o abstractizare de nivel înalt care recunoaște automat modelele de atingeri și gestionează stările. touchesBegan — o metodă de nivel scăzut a UIResponder care necesită urmărirea manuală a coordonatelor, sincronizării și anulării atingerilor. Gesture Recognizer este mai simplu, mai fiabil și preferabil pentru gesturile standard; touchesBegan este justificat doar pentru grafica personalizată.

Gesture Recognizer funcționează în SwiftUI?

În SwiftUI nativ se folosesc modificatori: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture. Aceștia sunt analogi declaraivi ai UIGestureRecognizer, integrați în ierarhia SwiftUI. La nevoie, puteți împacheta un recunoscător UIKit prin UIViewRepresentable, dar Apple recomandă utilizarea gesturilor native SwiftUI.

Rezumat

  • UIGestureRecognizer — abstractizare UIKit pentru descompunerea logicii de recunoaștere a gesturilor în obiecte separate cu gestionare automată a stărilor.
  • 7 subclase încorporate acoperă 95% din gesturile tipice: tap, glisare, panoramare, ciupire, rotire, apăsare lungă și glisare de la margine.
  • Fiecare recunoscător trece prin 7 stări — de la .possible la .ended/.failed, permițând urmărirea precisă a gesturilor discrete și continue.
  • Metoda require(toFail:) rezolvă conflictele între gesturi pe aceeași vizualizare, stabilind prioritatea de recunoaștere.
  • În SwiftUI se folosesc modificatori declaraivi de gesturi, dar recunoscătorii UIKit sunt accesibili prin UIViewRepresentable.
  • Gesture Recognizer este obligatoriu pentru proiectele UIKit; touchesBegan este justificat doar pentru desenarea personalizată și grafica de nivel scăzut.
  • Folosiți require(toFail:) pentru perechile tap/double-tap și gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) pentru gesturi paralele.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și