← Назад к вопросам

Отрабатывает ли UIGepstureRecognaizer через UIResponder?

1.3 Junior🔥 242 комментариев
#CI/CD и инструменты разработки

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Механизм работы UIGestureRecognizer и его интеграция с UIResponder

UIGestureRecognizer работает параллельно с цепочкой UIResponder, но имеет собственную систему распознавания жестов. Это не классический механизм через hitTest(_:with:) и point(inside:with:), хотя они тесно взаимосвязаны.

Ключевые принципы взаимодействия

  1. Отдельная система распознавания UIGestureRecognizer — это независимый объект, который анализирует поток событий касания (UITouch), получаемый от системы. Он не является частью цепочки UIResponder (которая включает touchesBegan, touchesMoved и т.д.).

  2. Приоритет жестов над методами touches Когда распознаватель жестов прикреплен к UIView, система отдает приоритет его логике. Если жест успешно распознан, соответствующие методы touches в UIResponder (такие как touchesBegan) не вызываются для этого представления, если не указано иное.

    let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
    tapRecognizer.cancelsTouchesInView = true // По умолчанию true — touches методы не вызовутся
    myView.addGestureRecognizer(tapRecognizer)
    
  3. Настройка взаимодействия через cancelsTouchesInView Это свойство управляет блокировкой событий touches:

    • true (по умолчанию): при успешном распознавании жеста все последующие события касания для этого представления отменяются (touchesCancelled).
    • false: методы touches будут вызваны параллельно с обработчиком жеста.
  4. Зависимость от hit-testing Для работы жеста требуется, чтобы касание произошло в пределах bounds представления, к которому он прикреплен. Механизм hitTest(_:with:) определяет, какое представление должно получить событие касания. Если касание не попадает в представление, его распознаватель жестов не активируется.

Пример конкурентного вызова жеста и touches-методов

class CustomView: UIView {
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        print("touchesBegan вызван")
    }
    
    @objc func handleTap() {
        print("Жест распознан")
    }
}

// Настройка
let customView = CustomView()
let recognizer = UITapGestureRecognizer(target: customView, action: #selector(CustomView.handleTap))
recognizer.cancelsTouchesInView = false // Позволяет работать и touchesBegan, и жесту
customView.addGestureRecognizer(recognizer)

Важные аспекты интеграции

  • Метод require(toFail:) позволяет устанавливать зависимости между распознавателями, определяя порядок их обработки.
  • Состояния жеста (.possible, .began, .changed, .ended, .cancelled, .failed) управляются внутренней логикой распознавателя, независимо от состояния UIResponder.
  • Отмена жеста может происходить при вызове метода touchesCancelled в UIResponder, если система прервет обработку (например, из-за скролла UIScrollView).

Итог

UIGestureRecognizer не работает напрямую через UIResponder, а использует параллельный механизм обработки событий. Он интегрирован в систему событий iOS так, чтобы либо замещать стандартные методы touches (по умолчанию), либо сосуществовать с ними (при cancelsTouchesInView = false). Понимание этого разделения критически важно для корректной обработки мультитач-взаимодействий, особенно в сложных иерархиях представлений, где могут возникать конфликты между жестами и собственными обработками касаний.

Отрабатывает ли UIGepstureRecognaizer через UIResponder? | PrepBro