Gesture Recognizer — o que é, manipulação de toques em iOS

Autor: IT Sectr Publicado: 2026-02-27 Tempo de leitura: 8 min
Gesture Recognizer é uma abstração no UIKit que converte uma sequência de toques do usuário em um gesto reconhecido: tap, swipe, pressão longa, pinça ou rotação. Em vez de rastrear coordenadas manualmente nos métodos touchesBegan/touchesMoved, o desenvolvedor adiciona um objeto UIGestureRecognizer pronto ao UIView e implementa um método de ação. De acordo com a Documentação do Desenvolvedor Apple, UIGestureRecognizer suporta 7 subclasses integradas que cobrem 95% dos gestos típicos em aplicativos móveis.

Principais pontos

  • UIGestureRecognizer é uma classe abstrata do UIKit para reconhecer padrões de toque: taps, swipes, pinças, rotações e pressões longas.
  • 7 subclasses integradas: UITapGestureRecognizer, UISwipeGestureRecognizer, UIPinchGestureRecognizer, UIRotationGestureRecognizer, UILongPressGestureRecognizer, UIPanGestureRecognizer, UIScreenEdgePanGestureRecognizer.
  • Cada reconhecedor tem um estado (possible, began, changed, ended, cancelled, failed) que é atualizado conforme os dedos se movem.
  • Para resolver conflitos entre gestos, usa-se o método require(toFail:) para definir a prioridade de reconhecimento.
  • Gesture Recognizer funciona com UIKit e UIViewRepresentable no SwiftUI, mas SwiftUI nativo usa modificadores de gestos.

O que é Gesture Recognizer?

UIGestureRecognizer é uma classe base abstrata no UIKit que decompõe o processo de reconhecimento de gestos em objetos separados. Cada subclass lida com um tipo de gesto: UITapGestureRecognizer lida com um tap com um número específico de toques, UISwipeGestureRecognizer lida com um swipe em uma direção determinada. O desenvolvedor adiciona o reconhecedor ao UIView através do método addGestureRecognizer(:), e o UIKit rastreia automaticamente os toques, atualiza o estado e chama uma ação ao reconhecer.

Antes do UIGestureRecognizer (iOS 3.2, 2010), os desenvolvedores sobrescreviam métodos do UIResponder — touchesBegan, touchesMoved, touchesEnded — e analisavam manualmente as trajetórias dos toques. Isso causava duplicação de código e erros ao lidar com toques simultâneos. A Apple encapsulou essa lógica no UIGestureRecognizer, adicionando suporte para multitoque, cancelamento de gestos e operação simultânea de vários reconhecedores em uma mesma view.

De acordo com as sessões da WWDC, o Gesture Recognizer lida com até 11 toques simultâneos no iPad e 5 no iPhone. Na IT Sectr, usamos UIGestureRecognizer como a forma padrão de lidar com entrada do usuário em todos os projetos UIKit — isso eliminou bugs associados ao rastreio manual de touchesBegan.

Estados do UIGestureRecognizer

Cada UIGestureRecognizer passa por 7 estados possíveis, definidos no enum UIGestureRecognizer.State. Esses estados refletem o ciclo de vida do reconhecimento: desde a deteção do toque até a conclusão ou cancelamento. Compreender os estados é crítico para implementar reconhecedores personalizados e depurar conflitos.

Estado Significado Quando ocorre
.possible Estado inicial, gesto ainda não reconhecido Imediatamente após ser adicionado a uma view
.began Gesto reconhecido e começou a executar No primeiro movimento do dedo para pan/longPress
.changed Parâmetros do gesto mudaram (coordenadas, ângulo) Em cada movimento do dedo
.ended Utilizador levantou o dedo, gesto concluído No touchesEnded
.cancelled Gesto interrompido pelo sistema (chamada recebida, mudança de orientação) No touchesCancelled
.failed Gesto não reconhecido conforme as condições No touchesCancelled sem reconhecimento
.recognized Sinónimo de .ended; gesto reconhecido com sucesso Igual ao .ended

Gestos discretos (tap, swipe) passam de .possible diretamente para .ended ou .failed. Gestos contínuos (pan, pinch, rotation, longPress) percorrem .possible → .began → .changed (repetidamente) → .ended. No método de ação, verifique gestureRecognizer.state — isto permite distinguir o início, a mudança e o fim de um gesto.

Tipos de gestos no iOS

UIKit fornece 7 subclasses integradas de UIGestureRecognizer, cobrindo a maioria dos cenários de interação. Cada subclass tem configurações específicas: numberOfTapsRequired para tap, direction para swipe, minimumPressDuration para pressão longa.

  • UITapGestureRecognizer — reconhece taps simples e múltiplos. Configurável número de taps (numberOfTapsRequired) e dedos (numberOfTouchesRequired). Usado para botões, links, seleção de elementos.
  • UISwipeGestureRecognizer — reconhece um swipe numa de quatro direções (right, left, up, down). A propriedade direction define a direção; numberOfTouchesRequired define o número de dedos.
  • UIPanGestureRecognizer — gesto contínuo para arrastar. O método translation(in:) devolve o deslocamento do ponto inicial. Usado para drag-and-drop, carrosséis, pull-to-refresh.
  • UIPinchGestureRecognizer — escalonamento com dois dedos. A propriedade scale reflete o fator de escala atual. Detalhado no artigo Pinch-to-Zoom.
  • UIRotationGestureRecognizer — rotação com dois dedos. A propriedade rotation armazena o ângulo em radianos. Usado para rodar imagens, mapas, telas.
  • UILongPressGestureRecognizer — pressão longa. Parâmetros: minimumPressDuration (segundos), allowableMovement (píxeis). Usado para menus contextuais, arrasto de elementos.
  • UIScreenEdgePanGestureRecognizer — deslizar da borda do ecrã. A propriedade edges especifica qual borda rastrear. Usado para gestos de navegação, painéis de notificações.

Para gestos personalizados (por exemplo, desenhar um ziguezague), cria-se uma subclass de UIGestureRecognizer sobrescrevendo touchesBegan, touchesMoved, touchesEnded e atualizando o estado. A Apple recomenda usar as classes integradas sempre que possível — elas são otimizadas e interagem corretamente entre si.

Resolução de conflitos entre gestos

Quando vários UIGestureRecognizer são usados numa mesma UIView (por exemplo, tap e duplo tap), ocorre um conflito de reconhecimento: num duplo tap, o tap simples dispara primeiro. A Apple fornece o método require(toFail:) para atrasar o reconhecimento de um gesto até que outro falhe.

O mecanismo funciona assim: ao chamar tapRecognizer.require(toFail: doubleTapRecognizer), especifica-se que tapRecognizer transitará para o estado .recognized apenas depois de doubleTapRecognizer terminar em .failed. Isto adiciona um atraso de ~0,3 segundos antes de executar o tap simples — o utilizador toca duas vezes e o primeiro tap é ignorado. Uma abordagem alternativa é o delegado UIGestureRecognizerDelegate com o método gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:), que permite reconhecimento simultâneo (por exemplo, pan + pinch para um mapa).

De acordo com a WWDC 2020, cerca de 15% dos erros em aplicações UIKit estão relacionados com configuração incorreta de conflitos de gestos. Na IT Sectr, padronizámos a abordagem: cada ecrã tem um esquema de gestos com prioridades require(toFail:) — isto eliminou completamente os erros de dupla ativação de taps.

Exemplos de código em Swift

Exemplo 1: UITapGestureRecognizer — Tap em imagem

Adiciona um manipulador de tap simples ao UIImageView. Ao tocar, a imagem muda de opacidade — um exemplo simples que mostra a vinculação de um gesto a uma view.

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

Ponto chave: isUserInteractionEnabled no UIImageView é false por defeito — sem esta flag, o Gesture Recognizer não receberá toques. Para UIView e UIButton, esta flag está ativada por defeito. O método de ação aceita um parâmetro UITapGestureRecognizer, através do qual se pode obter location(in:) para determinar as coordenadas do tap.

Exemplo 2: UISwipeGestureRecognizer — Deslizar para navegar

Implementa um deslize para a esquerda para voltar ao ecrã anterior. Demonstra a configuração de direção e a vinculação do gesto à view raiz do 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 é um gesto discreto: transita para .recognized imediatamente após o reconhecimento, sem estados .changed intermédios. Portanto, não é necessário verificar o estado na ação — o gesto ou é reconhecido (a ação dispara) ou não. A propriedade direction aceita um de quatro valores: .left, .right, .up, .down. Para suportar múltiplas direções, crie reconhecedores separados para cada uma.

Exemplo 3: Combinação de gestos com require(toFail:)

Mostra como configurar tap simples e duplo numa mesma view sem conflito. O reconhecedor de duplo tap tem prioridade — o tap simples dispara apenas se o duplo tap não for reconhecido.

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

Sem require(toFail:), num duplo tap, handleSingleTap dispara primeiro, depois handleDoubleTap — isto quebra a UX. Com require(toFail:), o tap simples espera ~0,3 segundos para garantir que um segundo tap não se segue. Na IT Sectr, este padrão é usado em editores de imagem e galerias, onde um duplo tap faz zoom e um tap simples seleciona um elemento.

Perguntas frequentes

Posso usar vários Gesture Recognizers numa mesma view?

Sim, UIView suporta várias instâncias de UIGestureRecognizer simultaneamente. Para resolver conflitos, use o método require(toFail:) que define a ordem de reconhecimento. Para operação paralela de gestos (por exemplo, pan + pinch num mapa), implemente o método delegado gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) retornando true.

Como o UIGestureRecognizer difere do touchesBegan?

UIGestureRecognizer é uma abstração de alto nível que reconhece automaticamente padrões de toque e gere estados. touchesBegan é um método de baixo nível do UIResponder que requer rastreio manual de coordenadas, temporização e cancelamento de toques. Gesture Recognizer é mais simples, fiável e preferível para gestos padrão; touchesBegan só se justifica para gráficos personalizados.

O Gesture Recognizer funciona no SwiftUI?

O SwiftUI nativo usa modificadores: onTapGesture, onLongPressGesture, DragGesture, MagnificationGesture, RotationGesture. Estes são análogos declarativos do UIGestureRecognizer integrados na hierarquia do SwiftUI. Se necessário, pode-se envolver um reconhecedor UIKit através de UIViewRepresentable, mas a Apple recomenda usar gestos nativos do SwiftUI.

Resumo

  • UIGestureRecognizer é uma abstração do UIKit para decompor a lógica de reconhecimento de gestos em objetos separados com gestão automática de estados.
  • 7 subclasses integradas cobrem 95% dos gestos típicos: tap, swipe, pan, pinch, rotation, long press e edge swipe.
  • Cada reconhecedor passa por 7 estados — desde .possible até .ended/.failed, permitindo rastreio preciso de gestos discretos e contínuos.
  • O método require(toFail:) resolve conflitos entre gestos numa mesma view definindo prioridade de reconhecimento.
  • SwiftUI usa modificadores de gestos declarativos, mas os reconhecedores UIKit estão disponíveis através de UIViewRepresentable.
  • Gesture Recognizer é obrigatório para projetos UIKit; touchesBegan só se justifica para desenho personalizado e gráficos de baixo nível.
  • Use require(toFail:) para pares tap/duplo tap e gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) para gestos paralelos.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também