Отрабатывает ли UIGepstureRecognaizer через UIResponder?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Механизм работы UIGestureRecognizer и его интеграция с UIResponder
UIGestureRecognizer работает параллельно с цепочкой UIResponder, но имеет собственную систему распознавания жестов. Это не классический механизм через hitTest(_:with:) и point(inside:with:), хотя они тесно взаимосвязаны.
Ключевые принципы взаимодействия
-
Отдельная система распознавания UIGestureRecognizer — это независимый объект, который анализирует поток событий касания (
UITouch), получаемый от системы. Он не является частью цепочкиUIResponder(которая включаетtouchesBegan,touchesMovedи т.д.). -
Приоритет жестов над методами touches Когда распознаватель жестов прикреплен к
UIView, система отдает приоритет его логике. Если жест успешно распознан, соответствующие методыtouchesвUIResponder(такие какtouchesBegan) не вызываются для этого представления, если не указано иное.let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap)) tapRecognizer.cancelsTouchesInView = true // По умолчанию true — touches методы не вызовутся myView.addGestureRecognizer(tapRecognizer) -
Настройка взаимодействия через
cancelsTouchesInViewЭто свойство управляет блокировкой событийtouches:true(по умолчанию): при успешном распознавании жеста все последующие события касания для этого представления отменяются (touchesCancelled).false: методыtouchesбудут вызваны параллельно с обработчиком жеста.
-
Зависимость от 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). Понимание этого разделения критически важно для корректной обработки мультитач-взаимодействий, особенно в сложных иерархиях представлений, где могут возникать конфликты между жестами и собственными обработками касаний.