Ответ
Hit Test — это механизм UIKit для определения представления (UIView), которое должно получить и обработать событие касания (touch event). Система рекурсивно проходит иерархию вью, начиная с корневого окна (UIWindow), чтобы найти самое глубокое (frontmost) представление, находящееся под точкой касания.
Алгоритм работы (в упрощенном виде):
- Проверяет, находится ли точка внутри bounds вью (
bounds.contains(point)). - Проверяет свойства, влияющие на взаимодействие:
isUserInteractionEnabled,isHiddenиalpha > 0.01. - Для прошедших проверку вью рекурсивно вызывает
hitTest(_:with:)для их подвью (порядок обхода — с конца массиваsubviews, т.е. от верхних к нижним). - Если точка не попала ни в одну подвью, возвращает саму эту вью как результат.
Зачем переопределять hitTest? Для изменения области отклика вью или перенаправления событий.
Пример: Расширение кликабельной области кнопки за её видимые bounds.
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// 1. Определяем расширенную область (например, +20pt со всех сторон)
let expandedBounds = bounds.insetBy(dx: -20, dy: -20)
// 2. Если точка в расширенной области и вью может получать события...
if expandedBounds.contains(point) && !isHidden && isUserInteractionEnabled && alpha > 0.01 {
// 3. ...возвращаем эту кнопку как цель для события
return self
}
// 4. Иначе используем стандартное поведение
return super.hitTest(point, with: event)
}
Важно: Не забывайте вызывать super.hitTest в default-кейсе, чтобы не сломать стандартное поведение для других областей.