Добавить в корзинуПозвонить
Найти в Дзене

Swift Interview. Средний уровень. UIKit. Расскажите про ResponderChain и hit-testing

Тема не сложная, но на ней часто возникают проблемы у соискателей на middle позицию. В продолжении часто бывают дополнительные вопросы, связанные с кастомизацией обработок нажатий. Например, в посте с собеседованием вопросы 15, 16. Что будет, если в TapGestureRecognizer в target вместо self сделаем nil? Можно ли при выключенном UserInteraction во view обрабатывать события нажатия в её subview? hitTest — это метод класса UIView, используемый для определения того, какая именно вью (view) должна получить событие касания. • Функция: Метод возвращает UIView, которая содержит точку нажатия, или nil, если касание было вне вью. • Использование: Применяется, когда нужно обрабатывать нажатия на перекрывающихся вью, кнопках, или при создании кастомных интерактивных элементов (например, сделать кнопку "нажимаемой" за пределами ее границ). • Алгоритм: 1) Проверяет, попадает ли точка в саму вью (с помощью point(inside:with:)) 2) Проверяет, включено ли взаимодействие (isUserInteractionEnabled), скрыт

Тема не сложная, но на ней часто возникают проблемы у соискателей на middle позицию. В продолжении часто бывают дополнительные вопросы, связанные с кастомизацией обработок нажатий. Например, в посте с собеседованием вопросы 15, 16. Что будет, если в TapGestureRecognizer в target вместо self сделаем nil? Можно ли при выключенном UserInteraction во view обрабатывать события нажатия в её subview?

hitTest — это метод класса UIView, используемый для определения того, какая именно вью (view) должна получить событие касания.

• Функция: Метод возвращает UIView, которая содержит точку нажатия, или nil, если касание было вне вью.

• Использование: Применяется, когда нужно обрабатывать нажатия на перекрывающихся вью, кнопках, или при создании кастомных интерактивных элементов (например, сделать кнопку "нажимаемой" за пределами ее границ).

• Алгоритм:

1) Проверяет, попадает ли точка в саму вью (с помощью point(inside:with:))

2) Проверяет, включено ли взаимодействие (isUserInteractionEnabled), скрыта ли она (isHidden) и прозрачна ли (alpha < 0.01)

3) Если все условия соблюдены, рекурсивно вызывает hitTest для своих подопечных (subviews)

• Игнорирование: Если hitTest возвращает nil, вью и её подпредставления не будут обрабатывать касание.

При переопределении hitTest в своих вью (например, для создания вью, кликабельной за пределами bounds), разработчики часто меняют логику попадания point(inside:with:)

Responder Chain — это ключевой механизм в iOS (UIKit) для обработки событий и передачи сообщений через иерархию объектов. Является паттерном, который динамически определяет объект, ответственный за обработку события(касание, встряхивание, действия из меню и т.д.). Если первый потенциальный обработчик не может обработать событие, оно передаётся дальше по цепочке.

• Базовый принцип:

1) Событие происходит (например, касание)

2) Система находит первого ответчика (First Responder)

3) Если он не обрабатывает событие, оно передаётся вверх по иерархии ответчиков: view → superview → ... → viewController → window → application → appDelegate

Что будет, если в TapGestureRecognizer в target вместо self сделаем nil?

Система не игнорирует жест и не крашится. Вместо этого активируется механизм Responder Chain. При срабатывании жеста система пытается найти объект, который может обработать этот action:

Начинает с firstResponder (обычно это view, на котором добавлен жест)

Идет вверх по цепочке: view → superview → ... → viewController → window → application → appDelegate

На каждом уровне вызывает canPerformAction(_:withSender:)

Когда система ищет обработчик через Responder Chain и не находит его, краша нет. Просто ничего не происходит

Ответ на второй дополнительный вопрос и более подробный разбор темы в статье 👇👇👇 Карта необходимых знаний/ компетенции уже с этим вопросом в постоянно обновляемом посте на Дзене по ссылке👇👇👇