Gesture Recognizer: qué es, manejo de toques en iOS

Autor: IT Sectr Publicado: 2026-02-27 Tiempo de lectura: 8 min
Gesture Recognizer es una abstracción en UIKit que convierte una secuencia de toques del usuario en un gesto reconocido: tap, swipe, pulsación larga, pellizco o rotación. En lugar de rastrear coordenadas manualmente en los métodos touchesBegan/touchesMoved, el desarrollador añade un objeto UIGestureRecognizer listo para usar en UIView e implementa un método de acción. Según la Documentación para Desarrolladores de Apple, UIGestureRecognizer admite 7 subclases incorporadas que cubren el 95% de los gestos típicos en aplicaciones móviles.

Puntos clave

  • UIGestureRecognizer es una clase abstracta de UIKit para reconocer patrones de toque: taps, swipes, pellizcos, rotaciones y pulsaciones largas.
  • 7 subclases incorporadas: UITapGestureRecognizer, UISwipeGestureRecognizer, UIPinchGestureRecognizer, UIRotationGestureRecognizer, UILongPressGestureRecognizer, UIPanGestureRecognizer, UIScreenEdgePanGestureRecognizer.
  • Cada reconocedor tiene un estado (possible, began, changed, ended, cancelled, failed) que se actualiza a medida que los dedos se mueven.
  • Para resolver conflictos entre gestos, se usa el método require(toFail:) para establecer la prioridad de reconocimiento.
  • Gesture Recognizer funciona con UIKit y UIViewRepresentable en SwiftUI, pero SwiftUI nativo utiliza modificadores de gestos.

¿Qué es Gesture Recognizer?

UIGestureRecognizer es una clase base abstracta en UIKit que descompone el proceso de reconocimiento de gestos en objetos separados. Cada subclase maneja un tipo de gesto: UITapGestureRecognizer maneja un tap con un número específico de toques, UISwipeGestureRecognizer maneja un swipe en una dirección determinada. El desarrollador añade el reconocedor a UIView mediante el método addGestureRecognizer(:), y UIKit rastrea automáticamente los toques, actualiza el estado y llama a una acción al reconocerlo.

Antes de UIGestureRecognizer (iOS 3.2, 2010), los desarrolladores sobrescribían los métodos de UIResponder — touchesBegan, touchesMoved, touchesEnded — y analizaban manualmente las trayectorias de los toques. Esto provocaba duplicación de código y errores al manejar toques simultáneos. Apple encapsuló esta lógica en UIGestureRecognizer, añadiendo soporte para multitáctil, cancelación de gestos y operación simultánea de múltiples reconocedores en una misma vista.

Según las sesiones de WWDC, Gesture Recognizer maneja hasta 11 toques simultáneos en iPad y 5 en iPhone. En IT Sectr, usamos UIGestureRecognizer como la forma estándar de manejar la entrada del usuario en todos los proyectos UIKit — esto eliminó los errores asociados con el rastreo manual de touchesBegan.

Estados de UIGestureRecognizer

Cada UIGestureRecognizer pasa por 7 estados posibles, definidos en el enum UIGestureRecognizer.State. Estos estados reflejan el ciclo de vida del reconocimiento: desde la detección del toque hasta la finalización o cancelación. Comprender los estados es crítico para implementar reconocedores personalizados y depurar conflictos.

Estado Significado Cuándo ocurre
.possible Estado inicial, gesto aún no reconocido Inmediatamente después de añadirse a una vista
.began Gesto reconocido y comenzó a ejecutarse En el primer movimiento del dedo para pan/longPress
.changed Los parámetros del gesto cambiaron (coordenadas, ángulo) En cada movimiento del dedo
.ended El usuario levantó el dedo, gesto completado En touchesEnded
.cancelled Gesto interrumpido por el sistema (llamada entrante, cambio de orientación) En touchesCancelled
.failed Gesto no reconocido según las condiciones En touchesCancelled sin reconocimiento
.recognized Sinónimo de .ended; gesto reconocido exitosamente Igual que .ended

Los gestos discretos (tap, swipe) pasan de .possible directamente a .ended o .failed. Los gestos continuos (pan, pinch, rotation, longPress) recorren .possible → .began → .changed (repetidamente) → .ended. En el método de acción, verifica gestureRecognizer.state — esto permite distinguir el inicio, el cambio y el final de un gesto.

Tipos de gestos en iOS

UIKit proporciona 7 subclases incorporadas de UIGestureRecognizer, que cubren la mayoría de los escenarios de interacción. Cada subclase tiene configuraciones específicas: numberOfTapsRequired para tap, direction para swipe, minimumPressDuration para pulsación larga.

  • UITapGestureRecognizer — reconoce taps simples y múltiples. Configurable número de taps (numberOfTapsRequired) y dedos (numberOfTouchesRequired). Se usa para botones, enlaces, selección de elementos.
  • UISwipeGestureRecognizer — reconoce un deslizamiento en una de cuatro direcciones (right, left, up, down). La propiedad direction establece la dirección; numberOfTouchesRequired establece el número de dedos.
  • UIPanGestureRecognizer — gesto continuo para arrastrar. El método translation(in:) devuelve el desplazamiento desde el punto inicial. Se usa para drag-and-drop, carruseles, pull-to-refresh.
  • UIPinchGestureRecognizer — escalado con dos dedos. La propiedad scale refleja el factor de escala actual. Detallado en el artículo Pinch-to-Zoom.
  • UIRotationGestureRecognizer — rotación con dos dedos. La propiedad rotation almacena el ángulo en radianes. Se usa para rotar imágenes, mapas, lienzos.
  • UILongPressGestureRecognizer — pulsación larga. Parámetros: minimumPressDuration (segundos), allowableMovement (píxeles). Se usa para menús contextuales, arrastre de elementos.
  • UIScreenEdgePanGestureRecognizer — deslizamiento desde el borde de la pantalla. La propiedad edges especifica qué borde rastrear. Se usa para gestos de navegación, paneles de notificaciones.

Para gestos personalizados (por ejemplo, dibujar un zigzag), se crea una subclase de UIGestureRecognizer sobrescribiendo touchesBegan, touchesMoved, touchesEnded y actualizando el estado. Apple recomienda usar las clases incorporadas cuando sea posible — están optimizadas e interactúan correctamente entre sí.

Resolución de conflictos entre gestos

Cuando se usan múltiples UIGestureRecognizer en una misma UIView (por ejemplo, tap y doble tap), ocurre un conflicto de reconocimiento: en un doble tap, el tap simple se dispara primero. Apple proporciona el método require(toFail:) para retrasar el reconocimiento de un gesto hasta que otro falle.

El mecanismo funciona así: al llamar tapRecognizer.require(toFail: doubleTapRecognizer), se especifica que tapRecognizer pasará al estado .recognized solo después de que doubleTapRecognizer termine en .failed. Esto añade un retraso de ~0.3 segundos antes de ejecutar el tap simple — el usuario toca dos veces y el primer tap se ignora. Un enfoque alternativo es el delegado UIGestureRecognizerDelegate con el método gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:), que permite el reconocimiento simultáneo (por ejemplo, pan + pinch para un mapa).

Según WWDC 2020, alrededor del 15% de los errores en aplicaciones UIKit están relacionados con una configuración incorrecta de conflictos de gestos. En IT Sectr, estandarizamos el enfoque: cada pantalla tiene un esquema de gestos con prioridades require(toFail:) — esto eliminó por completo los errores de doble activación de taps.

Ejemplos de código en Swift

Ejemplo 1: UITapGestureRecognizer — Tap en imagen

Añade un manejador de tap simple a UIImageView. Al tocar, la imagen cambia de opacidad — un ejemplo sencillo que muestra la vinculación de 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 clave: isUserInteractionEnabled en UIImageView es false por defecto — sin esta bandera, Gesture Recognizer no recibirá toques. Para UIView y UIButton, esta bandera está activada por defecto. El método de acción acepta un parámetro UITapGestureRecognizer, a través del cual se puede obtener location(in:) para determinar las coordenadas del tap.

Ejemplo 2: UISwipeGestureRecognizer — Deslizar para navegar

Implementa un deslizamiento a la izquierda para volver a la pantalla anterior. Demuestra la configuración de dirección y la vinculación del gesto a la vista raíz del controlador.

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 es un gesto discreto: pasa a .recognized inmediatamente después del reconocimiento, sin estados .changed intermedios. Por lo tanto, no es necesario verificar el estado en la acción — el gesto se reconoce (la acción se dispara) o no. La propiedad direction acepta uno de cuatro valores: .left, .right, .up, .down. Para admitir múltiples direcciones, crea reconocedores separados para cada una.

Ejemplo 3: Combinación de gestos con require(toFail:)

Muestra cómo configurar tap simple y doble en una misma vista sin conflicto. El reconocedor de doble tap tiene prioridad — el tap simple se dispara solo si el doble tap no se reconoce.

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

Sin require(toFail:), en un doble tap, handleSingleTap se dispara primero, luego handleDoubleTap — esto rompe la UX. Con require(toFail:), el tap simple espera ~0.3 segundos para asegurarse de que no sigue un segundo tap. En IT Sectr, este patrón se usa en editores de imágenes y galerías, donde un doble tap hace zoom y un tap simple selecciona un elemento.

Preguntas frecuentes

¿Se pueden usar varios Gesture Recognizers en una misma vista?

Sí, UIView admite múltiples instancias de UIGestureRecognizer simultáneamente. Para resolver conflictos, usa el método require(toFail:) que establece el orden de reconocimiento. Para la operación paralela de gestos (por ejemplo, pan + pinch en un mapa), implementa el método delegado gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) devolviendo true.

¿En qué se diferencia UIGestureRecognizer de touchesBegan?

UIGestureRecognizer es una abstracción de alto nivel que reconoce automáticamente patrones de toque y gestiona estados. touchesBegan es un método de bajo nivel de UIResponder que requiere seguimiento manual de coordenadas, temporización y cancelación de toques. Gesture Recognizer es más simple, fiable y preferible para gestos estándar; touchesBegan solo se justifica para gráficos personalizados.

¿Gesture Recognizer funciona en SwiftUI?

SwiftUI nativo utiliza modificadores: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture. Estos son análogos declarativos de UIGestureRecognizer integrados en la jerarquía de SwiftUI. Si es necesario, se puede envolver un reconocedor UIKit mediante UIViewRepresentable, pero Apple recomienda usar gestos nativos de SwiftUI.

Resumen

  • UIGestureRecognizer es una abstracción de UIKit para descomponer la lógica de reconocimiento de gestos en objetos separados con gestión automática de estados.
  • 7 subclases incorporadas cubren el 95% de los gestos típicos: tap, swipe, pan, pinch, rotation, long press y edge swipe.
  • Cada reconocedor pasa por 7 estados — desde .possible hasta .ended/.failed, permitiendo un seguimiento preciso de gestos discretos y continuos.
  • El método require(toFail:) resuelve conflictos entre gestos en una misma vista estableciendo la prioridad de reconocimiento.
  • SwiftUI utiliza modificadores de gestos declarativos, pero los reconocedores UIKit están disponibles mediante UIViewRepresentable.
  • Gesture Recognizer es obligatorio para proyectos UIKit; touchesBegan solo se justifica para dibujo personalizado y gráficos de bajo nivel.
  • Usa require(toFail:) para pares tap/doble tap y gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) para gestos paralelos.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también