Embora a maioria dos documentos da apple seja muito bem escrita, acho que o ' Event Handling Guide for iOS ' é uma exceção. É difícil para mim entender claramente o que foi descrito lá.
O documento diz:
No teste de acerto, uma janela chama
hitTest:withEvent:
a visualização mais superior da hierarquia de visualizações; esse método prossegue chamando recursivamentepointInside:withEvent:
cada exibição na hierarquia de exibição que retorna YES, prosseguindo pela hierarquia até encontrar a subvisão dentro de cujos limites o toque ocorreu. Essa visualização se torna a visualização de teste de acerto.
Então é assim que apenas hitTest:withEvent:
a visão superior é chamada pelo sistema, que chama pointInside:withEvent:
todas as subvisões, e se o retorno de uma subvisualização específica for SIM, as chamadas pointInside:withEvent:
das subclasses dessa subvisualização?
Respostas:
Parece uma pergunta bastante básica. Mas eu concordo com você que o documento não é tão claro quanto outros documentos, então aqui está a minha resposta.
A implementação do
hitTest:withEvent:
UIResponder faz o seguinte:pointInside:withEvent:
deself
hitTest:withEvent:
retornaránil
. o fim da história.hitTest:withEvent:
mensagens para suas subvisões. inicia na subvisão de nível superior e continua em outras visualizações até que uma subvisão retorne um não-nil
objeto ou todas as subvisões recebam a mensagem.nil
objeto na primeira vez, a primeirahitTest:withEvent:
retornará esse objeto. o fim da história.nil
objeto, a primeirahitTest:withEvent:
retornaráself
Esse processo se repete recursivamente; portanto, normalmente a exibição em folha da hierarquia da exibição é retornada eventualmente.
No entanto, você pode substituir
hitTest:withEvent
para fazer algo diferente. Em muitos casos, a substituiçãopointInside:withEvent:
é mais simples e ainda oferece opções suficientes para ajustar a manipulação de eventos em seu aplicativo.fonte
hitTest:withEvent:
todas as subvisões são executadas eventualmente?hitTest:withEvent:
as visualizações (epointInside
se desejar), imprima um log e ligue[super hitTest...
para descobrir quemhitTest:withEvent:
é chamado em que ordem.Eu acho que você está confundindo subclasses com a hierarquia de visualizações. O que o documento diz é o seguinte. Digamos que você tenha essa hierarquia de visualizações. Por hierarquia, não estou falando sobre hierarquia de classes, mas visualizações na hierarquia de visualizações, da seguinte maneira:
Diga que você coloca o dedo dentro
D
. Aqui está o que vai acontecer:hitTest:withEvent:
é chamadoA
, a visualização superior da hierarquia de visualizações.pointInside:withEvent:
é chamado recursivamente em cada visualização.pointInside:withEvent:
é chamadoA
e retornaYES
pointInside:withEvent:
é chamadoB
e retornaNO
pointInside:withEvent:
é chamadoC
e retornaYES
pointInside:withEvent:
é chamadoD
e retornaYES
YES
, ele olhará para baixo na hierarquia para ver a subvisão onde o toque ocorreu. Neste caso, a partir deA
,C
eD
, seráD
.D
será a visualização de teste de impactofonte
hitTest:withEvent:
sobre B, C e D também são invocados. O que acontece se D é uma subvisão de C, não A? Acho que fiquei confuso ...A
voltariaYES
tão bem quantoC
e voltaD
?Acho esse teste de sucesso no iOS muito útil
Editar Swift 4:
fonte
Obrigado pelas respostas, eles me ajudaram a resolver a situação com visualizações de "sobreposição".
Suponha
X
- toque do usuário.pointInside:withEvent:
emB
retornosNO
, entãohitTest:withEvent:
retornaA
. Escrevi a categoriaUIView
para lidar com o problema quando você precisa receber um toque na vista superior mais visível .userInteractionEnabled
definidas comoNO
;self
,self
será considerado como resultado potencial.Observe que é
[self.subviewsreverseObjectEnumerator]
necessário seguir a hierarquia da vista de cima para baixo. E verifique paraclipsToBounds
não testar subvisões mascaradas.Uso:
hitTest:withEvent:
por esteO Guia oficial da Apple também fornece algumas boas ilustrações.
Espero que isso ajude alguém.
fonte
Mostra como este trecho!
fonte
O trecho de @lion funciona como um encanto. Eu o carreguei para o swift 2.1 e o usei como uma extensão para o UIView. Estou postando aqui, caso alguém precise.
Para usá-lo, basta substituir hitTest: point: withEvent na sua visualização da seguinte maneira:
fonte
Diagrama de classe
Teste de Acerto
Encontre um
First Responder
First Responder
Nesse caso, oUIView
point()
método mais profundo retornou verdadeirohitTest()
Parece internamenteEnviar evento de toque para o
First Responder
Vamos dar uma olhada no exemplo
Cadeia de resposta
Veja o exemplo
[Android onTouch]
fonte