Хотя большинство документов Apple написаны очень хорошо, я думаю, что « Руководство по обработке событий для iOS » является исключением. Мне трудно ясно понять, что там описано.
В документе говорится:
При тестировании попаданий окно вызывает
hitTest:withEvent:
самый верхний вид иерархии представлений; этот метод выполняется путем рекурсивного вызоваpointInside:withEvent:
каждого представления в иерархии представлений, которое возвращает YES, и далее по иерархии, пока не найдет подпредставление, в пределах которого произошло касание. Этот вид становится тестом на попадание.
Так это похоже на то hitTest:withEvent:
, что система вызывает только самый верхний вид, который вызывает pointInside:withEvent:
все подпредставления, и если возвращение из конкретного подпредставления - ДА, то вызовы pointInside:withEvent:
подклассов этого подпредставления?
Ответы:
Это кажется довольно основным вопросом. Но я согласен с вами, документ не так понятен, как другие документы, поэтому вот мой ответ.
Реализация
hitTest:withEvent:
в UIResponder делает следующее:pointInside:withEvent:
изself
hitTest:withEvent:
возвращаетсяnil
. конец истории.hitTest:withEvent:
сообщения своим подпредставлениям. оно начинается с подпредставления верхнего уровня и продолжается в других представлениях, пока подпредставление не возвращаетnil
необъект или пока все подпредставления не получат сообщение.nil
необъект в первый раз, первоеhitTest:withEvent:
возвращает этот объект. конец истории.nil
необъект, первоеhitTest:withEvent:
возвращаетself
Этот процесс повторяется рекурсивно, поэтому обычно в конечном итоге возвращается листовое представление иерархии представлений.
Тем не менее, вы можете изменить,
hitTest:withEvent
чтобы сделать что-то по-другому. Во многих случаях переопределениеpointInside:withEvent:
проще и все же предоставляет достаточно возможностей для настройки обработки событий в вашем приложении.источник
hitTest:withEvent:
в виду, что все подпредставления выполняются в конце концов?hitTest:withEvent:
ваши представления (и,pointInside
если хотите), распечатайте журнал и позвоните,[super hitTest...
чтобы узнать, чейhitTest:withEvent:
вызов вызывается в каком порядке.Я думаю, что вы путаете подклассы с иерархией представления. Документ говорит следующее. Скажем, у вас есть эта иерархия представлений. По иерархии я говорю не об иерархии классов, а о представлениях внутри иерархии представлений, а именно:
Скажем, ты вставил палец внутрь
D
. Вот что произойдет:hitTest:withEvent:
вызываетсяA
, самый верхний вид иерархии представлений.pointInside:withEvent:
вызывается рекурсивно на каждом представлении.pointInside:withEvent:
вызываетсяA
и возвращаетYES
pointInside:withEvent:
вызываетсяB
и возвращаетNO
pointInside:withEvent:
вызываетсяC
и возвращаетYES
pointInside:withEvent:
вызываетсяD
и возвращаетYES
YES
он будет смотреть вниз на иерархию, чтобы увидеть подпредставление, где произошло касание. В этом случае отA
,C
иD
, это будетD
.D
будет тест на попаданиеисточник
hitTest:withEvent:
о B, C и D, также вызываемых. Что произойдет, если D является подпредставлением C, а не A? Я думаю, что я запутался ...A
вернетсяYES
так же, какC
иD
делает?Я считаю, что это Хит-тестирование в iOS очень полезно
Редактировать Swift 4:
источник
Спасибо за ответы, они помогли мне решить ситуацию с «оверлейными» взглядами.
Предположим
X
- касание пользователя.pointInside:withEvent:
наB
возвращаетсяNO
, так чтоhitTest:withEvent:
возвращаетсяA
. Я написал категорию,UIView
чтобы решить проблему, когда вам нужно прикоснуться к наиболее заметному виду сверху.userInteractionEnabled
установленным значениемNO
;self
,self
будет рассматриваться как потенциальный результат.Обратите внимание,
[self.subviewsreverseObjectEnumerator]
необходимо следовать иерархии представления сверху вниз. И проверьте,clipsToBounds
чтобы не проверять скрытые подпредставления.Использование:
hitTest:withEvent:
на этоОфициальное руководство Apple также содержит несколько хороших иллюстраций.
Надеюсь, это кому-нибудь поможет.
источник
Это показывает, как этот фрагмент!
источник
Фрагмент @lion работает как шарм. Я портировал его на swift 2.1 и использовал как расширение для UIView. Я публикую это здесь на случай, если кому-то это понадобится.
Чтобы использовать его, просто переопределите hitTest: point: withEvent в вашем uiview следующим образом:
источник
Диаграмма классов
Тестирование Хита
Найти
First Responder
First Responder
в этом случае самый глубокийUIView
point()
метод которого вернул trueВнутренне
hitTest()
выглядит какОтправить сенсорное событие на
First Responder
Давайте посмотрим на пример
Сеть ответчика
Посмотрите на пример
[Android на ощупь]
источник