Gesture Recognizer — cos'è, gestione dei tocchi in iOS

Autore: IT Sectr Pubblicato: 2026-02-27 Tempo di lettura: 8 min
Gesture Recognizer è un'astrazione in UIKit che converte una sequenza di tocchi dell'utente in un gesto riconosciuto: tap, swipe, pressione lunga, pizzico o rotazione. Invece di tracciare manualmente le coordinate nei metodi touchesBegan/touchesMoved, lo sviluppatore aggiunge un oggetto UIGestureRecognizer già pronto a UIView e implementa un metodo di azione. Secondo la Documentazione per Sviluppatori Apple, UIGestureRecognizer supporta 7 sottoclassi integrate che coprono il 95% dei gesti tipici nelle applicazioni mobili.

Punti chiave

  • UIGestureRecognizer è una classe astratta di UIKit per riconoscere schemi di tocco: tap, swipe, pizzichi, rotazioni e pressioni lunghe.
  • 7 sottoclassi integrate: UITapGestureRecognizer, UISwipeGestureRecognizer, UIPinchGestureRecognizer, UIRotationGestureRecognizer, UILongPressGestureRecognizer, UIPanGestureRecognizer, UIScreenEdgePanGestureRecognizer.
  • Ogni riconoscitore ha uno stato (possible, began, changed, ended, cancelled, failed) che si aggiorna man mano che le dita si muovono.
  • Per risolvere i conflitti tra gesti, si usa il metodo require(toFail:) per impostare la priorità di riconoscimento.
  • Gesture Recognizer funziona con UIKit e UIViewRepresentable in SwiftUI, ma SwiftUI nativo usa modificatori di gesti.

Cos'è Gesture Recognizer?

UIGestureRecognizer è una classe base astratta in UIKit che scompone il processo di riconoscimento dei gesti in oggetti separati. Ogni sottoclasse gestisce un tipo di gesto: UITapGestureRecognizer gestisce un tap con un numero specifico di tocchi, UISwipeGestureRecognizer gestisce uno swipe in una direzione determinata. Lo sviluppatore aggiunge il riconoscitore a UIView tramite il metodo addGestureRecognizer(:), e UIKit traccia automaticamente i tocchi, aggiorna lo stato e chiama un'azione al riconoscimento.

Prima di UIGestureRecognizer (iOS 3.2, 2010), gli sviluppatori sovrascrivevano i metodi UIResponder — touchesBegan, touchesMoved, touchesEnded — e analizzavano manualmente le traiettorie dei tocchi. Ciò causava duplicazione di codice ed errori nella gestione dei tocchi simultanei. Apple ha incapsulato questa logica in UIGestureRecognizer, aggiungendo il supporto per multitouch, annullamento dei gesti e funzionamento simultaneo di più riconoscitori su una stessa vista.

Secondo le sessioni WWDC, Gesture Recognizer gestisce fino a 11 tocchi simultanei su iPad e 5 su iPhone. In IT Sectr, usiamo UIGestureRecognizer come metodo standard per gestire l'input utente in tutti i progetti UIKit — ciò ha eliminato i bug associati al tracciamento manuale di touchesBegan.

Stati di UIGestureRecognizer

Ogni UIGestureRecognizer attraversa 7 stati possibili, definiti nell'enum UIGestureRecognizer.State. Questi stati riflettono il ciclo di vita del riconoscimento: dalla rilevazione del tocco al completamento o all'annullamento. Comprendere gli stati è fondamentale per implementare riconoscitori personalizzati e debug dei conflitti.

Stato Significato Quando si verifica
.possible Stato iniziale, gesto non ancora riconosciuto Subito dopo essere stato aggiunto a una vista
.began Gesto riconosciuto e iniziato a eseguire Al primo movimento del dito per pan/longPress
.changed Parametri del gesto cambiati (coordinate, angolo) Ad ogni movimento del dito
.ended L'utente ha sollevato il dito, gesto completato A touchesEnded
.cancelled Gesto interrotto dal sistema (chiamata in arrivo, cambio di orientamento) A touchesCancelled
.failed Gesto non riconosciuto secondo le condizioni A touchesCancelled senza riconoscimento
.recognized Sinonimo di .ended; gesto riconosciuto con successo Come .ended

I gesti discreti (tap, swipe) passano da .possible direttamente a .ended o .failed. I gesti continui (pan, pinch, rotation, longPress) attraversano .possible → .began → .changed (ripetutamente) → .ended. Nel metodo di azione, controlla gestureRecognizer.state — questo permette di distinguere l'inizio, il cambiamento e la fine di un gesto.

Tipi di gesti in iOS

UIKit fornisce 7 sottoclassi integrate di UIGestureRecognizer, coprendo la maggior parte degli scenari di interazione. Ogni sottoclasse ha impostazioni specifiche: numberOfTapsRequired per il tap, direction per lo swipe, minimumPressDuration per la pressione lunga.

  • UITapGestureRecognizer — riconosce tap singoli e multipli. Configurabile numero di tap (numberOfTapsRequired) e dita (numberOfTouchesRequired). Usato per pulsanti, link, selezione di elementi.
  • UISwipeGestureRecognizer — riconosce uno swipe in una delle quattro direzioni (right, left, up, down). La proprietà direction imposta la direzione; numberOfTouchesRequired imposta il numero di dita.
  • UIPanGestureRecognizer — gesto continuo per trascinare. Il metodo translation(in:) restituisce l'offset dal punto iniziale. Usato per drag-and-drop, caroselli, pull-to-refresh.
  • UIPinchGestureRecognizer — ridimensionamento a due dita. La proprietà scale riflette il fattore di scala corrente. Dettagliato nell'articolo Pinch-to-Zoom.
  • UIRotationGestureRecognizer — rotazione a due dita. La proprietà rotation memorizza l'angolo in radianti. Usato per ruotare immagini, mappe, canvas.
  • UILongPressGestureRecognizer — pressione lunga. Parametri: minimumPressDuration (secondi), allowableMovement (pixel). Usato per menu contestuali, trascinamento di elementi.
  • UIScreenEdgePanGestureRecognizer — scorrimento dal bordo dello schermo. La proprietà edges specifica quale bordo tracciare. Usato per gesti di navigazione, pannelli di notifica.

Per gesti personalizzati (ad esempio, disegnare uno zigzag), si crea una sottoclasse di UIGestureRecognizer sovrascrivendo touchesBegan, touchesMoved, touchesEnded e aggiornando lo stato. Apple raccomanda di usare le classi integrate dove possibile — sono ottimizzate e interagiscono correttamente tra loro.

Risoluzione dei conflitti tra gesti

Quando più UIGestureRecognizer vengono usati su una stessa UIView (ad esempio, tap e doppio tap), si verifica un conflitto di riconoscimento: su un doppio tap, il tap singolo si attiva per primo. Apple fornisce il metodo require(toFail:) per ritardare il riconoscimento di un gesto finché un altro non fallisce.

Il meccanismo funziona così: chiamando tapRecognizer.require(toFail: doubleTapRecognizer), si specifica che tapRecognizer passerà allo stato .recognized solo dopo che doubleTapRecognizer termina in .failed. Questo aggiunge un ritardo di ~0,3 secondi prima di eseguire il tap singolo — l'utente tocca due volte e il primo tap viene ignorato. Un approccio alternativo è il delegato UIGestureRecognizerDelegate con il metodo gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:), che permette il riconoscimento simultaneo (ad esempio, pan + pinch per una mappa).

Secondo la WWDC 2020, circa il 15% dei bug nelle applicazioni UIKit è correlato a una configurazione errata dei conflitti di gesti. In IT Sectr, abbiamo standardizzato l'approccio: ogni schermata ha uno schema di gesti con priorità require(toFail:) — ciò ha eliminato completamente i bug di doppia attivazione dei tap.

Esempi di codice in Swift

Esempio 1: UITapGestureRecognizer — Tap su immagine

Aggiunge un gestore di tap singolo a UIImageView. Al tocco, l'opacità dell'immagine cambia — un semplice esempio che mostra il collegamento di un gesto a una vista.

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

Punto chiave: isUserInteractionEnabled su UIImageView è false per impostazione predefinita — senza questo flag, Gesture Recognizer non riceverà i tocchi. Per UIView e UIButton, questo flag è attivato per impostazione predefinita. Il metodo di azione accetta un parametro UITapGestureRecognizer, attraverso il quale si può ottenere location(in:) per determinare le coordinate del tap.

Esempio 2: UISwipeGestureRecognizer — Scorrere per navigare

Implementa uno swipe a sinistra per tornare alla schermata precedente. Mostra la configurazione della direzione e il collegamento del gesto alla vista radice del 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 è un gesto discreto: passa a .recognized immediatamente dopo il riconoscimento, senza stati .changed intermedi. Pertanto, non è necessario controllare lo stato nell'azione — il gesto o viene riconosciuto (l'azione si attiva) o no. La proprietà direction accetta uno dei quattro valori: .left, .right, .up, .down. Per supportare più direzioni, crea riconoscitori separati per ciascuna.

Esempio 3: Combinazione di gesti con require(toFail:)

Mostra come configurare tap singolo e doppio su una stessa vista senza conflitto. Il riconoscitore di doppio tap ha priorità — il tap singolo si attiva solo se il doppio tap non viene riconosciuto.

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

Senza require(toFail:), su un doppio tap, handleSingleTap si attiva prima, poi handleDoubleTap — questo compromette l'UX. Con require(toFail:), il tap singolo attende ~0,3 secondi per assicurarsi che non segua un secondo tap. In IT Sectr, questo pattern viene utilizzato negli editor di immagini e nelle gallerie, dove un doppio tap ingrandisce e un tap singolo seleziona un elemento.

Domande frequenti

Si possono usare più Gesture Recognizer su una stessa vista?

Sì, UIView supporta più istanze di UIGestureRecognizer simultaneamente. Per risolvere i conflitti, usa il metodo require(toFail:) che imposta l'ordine di riconoscimento. Per il funzionamento parallelo dei gesti (ad esempio, pan + pinch su una mappa), implementa il metodo delegato gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) restituendo true.

In cosa differisce UIGestureRecognizer da touchesBegan?

UIGestureRecognizer è un'astrazione di alto livello che riconosce automaticamente i pattern di tocco e gestisce gli stati. touchesBegan è un metodo di basso livello di UIResponder che richiede tracciamento manuale delle coordinate, temporizzazione e annullamento dei tocchi. Gesture Recognizer è più semplice, affidabile e preferibile per i gesti standard; touchesBegan è giustificato solo per grafica personalizzata.

Gesture Recognizer funziona in SwiftUI?

SwiftUI nativo usa modificatori: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture. Questi sono analoghi dichiarativi di UIGestureRecognizer integrati nella gerarchia SwiftUI. Se necessario, è possibile avvolgere un riconoscitore UIKit tramite UIViewRepresentable, ma Apple raccomanda di usare i gesti nativi di SwiftUI.

Riepilogo

  • UIGestureRecognizer è un'astrazione UIKit per scomporre la logica di riconoscimento dei gesti in oggetti separati con gestione automatica degli stati.
  • 7 sottoclassi integrate coprono il 95% dei gesti tipici: tap, swipe, pan, pinch, rotation, long press e edge swipe.
  • Ogni riconoscitore attraversa 7 stati — da .possible a .ended/.failed, consentendo il tracciamento preciso di gesti discreti e continui.
  • Il metodo require(toFail:) risolve i conflitti tra gesti su una stessa vista impostando la priorità di riconoscimento.
  • SwiftUI usa modificatori di gesti dichiarativi, ma i riconoscitori UIKit sono disponibili tramite UIViewRepresentable.
  • Gesture Recognizer è obbligatorio per i progetti UIKit; touchesBegan è giustificato solo per disegno personalizzato e grafica di basso livello.
  • Usa require(toFail:) per le coppie tap/doppio tap e gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) per gesti paralleli.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche