Что такое Hit Test в UIKit?

«Что такое Hit Test в UIKit?» — вопрос из категории UIKit, который задают на 29% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Hit Test — это механизм UIKit для определения представления (UIView), которое должно получить и обработать событие касания (touch event). Система рекурсивно проходит иерархию вью, начиная с корневого окна (UIWindow), чтобы найти самое глубокое (frontmost) представление, находящееся под точкой касания.

Алгоритм работы (в упрощенном виде):

  1. Проверяет, находится ли точка внутри bounds вью (bounds.contains(point)).
  2. Проверяет свойства, влияющие на взаимодействие: isUserInteractionEnabled, isHidden и alpha > 0.01.
  3. Для прошедших проверку вью рекурсивно вызывает hitTest(_:with:) для их подвью (порядок обхода — с конца массива subviews, т.е. от верхних к нижним).
  4. Если точка не попала ни в одну подвью, возвращает саму эту вью как результат.

Зачем переопределять 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-кейсе, чтобы не сломать стандартное поведение для других областей.