Ответ
Да, метод hitTest(_:with:) в UIView можно переопределить для кастомной логики определения, какое view должно получить касание.
Типичные сценарии использования:
- Расширение или сужение области касания.
- Игнорирование касаний для определенных subviews.
- Перенаправление событий.
Пример: расширение зоны касания
class TouchExtendedView: UIView {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
// 1. Стандартные проверки (обязательно)
guard self.isUserInteractionEnabled,
!self.isHidden,
self.alpha > 0.01,
self.point(inside: point, with: event) else {
return nil
}
// 2. Расширяем область проверки на 10 пунктов
let expandedBounds = self.bounds.insetBy(dx: -10, dy: -10)
guard expandedBounds.contains(point) else {
return nil
}
// 3. Рекурсивная проверка дочерних view (стандартное поведение)
for subview in subviews.reversed() {
let convertedPoint = subview.convert(point, from: self)
if let hitView = subview.hitTest(convertedPoint, with: event) {
return hitView
}
}
// 4. Если дочерние view не обработали, возвращаем self
return self
}
}
Best practices:
- Всегда выполняйте базовые проверки (
isUserInteractionEnabled,isHidden,alpha). - Для сложной геометрии используйте
point(inside:with:). - Проверяйте дочерние view в обратном порядке (
reversed()), так как они отрисовываются поверх друг друга. - Избегайте тяжелых вычислений внутри метода, так как он вызывается часто.