Ответ
Эти методы работают в тандеме для определения получателя touch-событий в иерархии UIView.
point(inside:with:)
- Назначение: Проверяет, находится ли заданная точка в пределах границ (bounds) текущего view.
- Возвращает:
Bool(true, если точка внутри). - Логика: Простая геометрическая проверка. Не учитывает иерархию subviews.
- Типичное использование: Переопределяется для расширения или изменения области отклика view без изменения его видимых границ.
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { // Увеличиваем область отклика на 10 пунктов во все стороны let expandedBounds = bounds.insetBy(dx: -10, dy: -10) return expandedBounds.contains(point) }
hitTest(_:with:)
- Назначение: Определяет самое глубокое (frontmost) view в иерархии, которое должно получить touch-событие для заданной точки.
- Возвращает:
UIView?(найденное view илиnil). - Алгоритм работы (рекурсивный):
- Проверяет, может ли view вообще получать события:
isUserInteractionEnabled,!isHidden,alpha > 0.01. - Вызывает
point(inside:with:)для себя. Если точка вне границ — возвращаетnil. - Если точка внутри, проходит по subviews в обратном порядке (от самого верхнего к нижнему), вызывая для каждого
hitTest. - Если один из subviews вернул не-nil view, возвращает его. Если нет — возвращает себя.
- Проверяет, может ли view вообще получать события:
- Типичное использование: Переопределяется для перенаправления событий или создания нестандартного поведения (например, игнорирование touches в определенной области).
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let hitView = super.hitTest(point, with: event) // Если событие должно попасть в прозрачную кнопку-оверлей, возвращаем её return (hitView == self) ? overlayButton : hitView }
Взаимосвязь: hitTest использует point(inside:with:) как один из шагов в своем алгоритме. Переопределение point(inside:with:) напрямую влияет на результат работы hitTest для этого view.