В этом уроке рассмотрим различные особенности работы с методами hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView?
и point(inside point: CGPoint, with event: UIEvent?) -> Bool
На эту тему встречается множество вопросов как теоретических, так и практических.
<aside> 💡 Вопросы и задания по этой теме встречались на интервью в компании Ivi, Mail и VK
</aside>
Для начала определимся с тем, что такое hit-testing и какую проблему он решает?
Hit-testing — это процесс определения того, пересекается ли точка, например, точка касания, с заданным графическим объектом, представленным на экране, например,
UIView
. iOS использует эту технику, чтобы определить, какойUIView
находится на переднем плане под пальцем пользователя, и может лиUIView
обработать касание. Он реализует это путем поиска в иерархии представлений с использованием алгоритма обхода в глубину (DFS) с обратным предварительным порядком (Reverse pre-order).
Реализуйте метод hitTest. Как он мог бы выглядеть в стандартной библиотеке UIKit
?
func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
//TODO: ???
}
func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
guard isUserInteractionEnabled, !isHidden, alpha > 0 else {
return nil
}
if self.point(inside: point, with: event) {
for subview in subviews.reversed() {
let convertedPoint = subview.convert(point, from: self)
if let hitView = subview.hitTest(convertedPoint, with: event) {
return hitView
}
}
return self
}
return nil
}
Как работает hitTest. [Источник](<https://smnh.me/hit-testing-in-ios>)
isUserInteractionEnabled == true
point(inside:, with:)
point(inside:, with:)
вернул false
, то возвращаем nil