Система использует два ключевых механизма: хит-тестирование (hit-testing) и иерархию вьюх.
Хит-тестирование (Hit-testing): Фреймворк UIKit использует метод hitTest(_:with:) корневой вьюхи окна (UIWindow) для определения, какая вьюха находится под точкой касания. Этот метод рекурсивно обходит иерархию вьюх, начиная с корневой.
Иерархия вьюх:
hitTest(_:with:) сначала проверяет, находится ли точка касания внутри границ текущей вьюхи. Если нет, метод возвращает nil.hitTest(_:with:) с той же точкой касания (преобразованной в координаты дочерней вьюхи).hitTest(_:with:) возвращает не-nil результат (т.е. она или одна из ее дочерних вьюх содержит точку), считается "попавшей" и этот результат возвращается вверх по иерархии.userInteractionEnabled = false, то система считает, что касание произошло в текущей вьюхе, и метод возвращает self.userInteractionEnabled текущей вьюхи равно false или hidden равно true, или alpha меньше 0.01, метод возвращает nil, даже если точка внутри границ.Процесс продолжается вниз по иерархии, пока не будет найдена самая нижняя в иерархии вьюха, содержащая точку касания. Эта вьюха становится hit-test view или hit-test result, и именно ей (или ее ближайшему подходящему предку) будет делегировано дальнейшее управление событием (методы touchesBegan, touchesMoved и т.д.).
Вот как можно переопределить hitTest или point(inside:with:) для кастомного поведения хит-тестирования:
swift
Метод point(inside:with:) вызывается методом hitTest(_:with:) для быстрой проверки, находится ли точка вообще внутри области вьюхи, прежде чем проверять дочерние вьюхи.
В итоге находится именно самая нижняя интерактивная вьюха в иерархии, чья геометрия содержит точку касания и у которой userInteractionEnabled равен true, hidden — false и alpha больше 0.01.