Работает ли UIGestureRecognizer через цепочку UIResponder?

Ответ

Да, UIGestureRecognizer интегрирован в систему событий UIResponder, но перехватывает и обрабатывает события касаний до того, как они достигнут стандартных методов UIResponder (таких как touchesBegan(_:with:)).

Последовательность обработки касания:

  1. Система (UIApplication -> UIWindow) отправляет объекты UITouch в цепочку responder'ов.
  2. Прикреплённые к view UIGestureRecognizer анализируют поток касаний.
  3. Если распознаватель определяет свой жест, он:
    • Вызывает свой целевой метод (action).
    • По умолчанию (cancelsTouchesInView = true) отменяет дальнейшую доставку этого касания методам view (touchesBegan и др.).
  4. Если жест не распознан или свойство cancelsTouchesInView = false, события касаний передаются дальше по цепочке UIResponder.

Пример настройки:

let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapRecognizer.cancelsTouchesInView = false // Позволяет touchesBegan также получить событие
view.addGestureRecognizer(tapRecognizer)

Ответ 18+ 🔞

Ну, слушай, вот тебе на пальцах, как эта магия с UIGestureRecognizer работает. Представь себе такую картину: у тебя есть view, и на него падает касание, как снег на голову.

Система, эта хитрая жопа, начинает раскидывать это касание по цепочке UIResponder. Но! Пока оно долетит до твоего родного touchesBegan, на его пути стоит наш мудак — UIGestureRecognizer. Он как вышибала в клубе: смотрит на поток касаний и думает — а, это мой жест? Тап? Свайп? Пинч?

И если он свой жест опознал, то он делает две вещи:

  1. Овердохуища радости и вызывает твой целевой метод (тот самый action).
  2. И, что самое главное, по умолчанию он говорит системе: «Всё, я тут разобрался, дальше это касание не пускать!». То есть твои touchesBegan и компания его уже не увидят. Нахуй отменил, короче.

Но если ты хочешь, чтобы и жест работал, и touchesBegan тоже что-то получал — есть волшебная палочка. Называется cancelsTouchesInView. Выставишь её в false, и распознаватель превращается из жадной собаки в вежливого официанта: «Жест я распознал, action вызвал, но, пожалуйста, вот ваши касания, sir, передаю дальше по цепочке».

Вот, смотри, как это в коде выглядит:

let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
tapRecognizer.cancelsTouchesInView = false // Теперь и тап сработает, и touchesBegan не обделят
view.addGestureRecognizer(tapRecognizer)

Вот и вся ебёная механика. Либо жест жрёт всё, либо делится, если его правильно попросить.