Si bien la mayoría de los documentos de Apple están muy bien escritos, creo que la ' Guía de manejo de eventos para iOS ' es una excepción. Es difícil para mí entender claramente lo que se ha descrito allí.
El documento dice:
En las pruebas de impacto, una ventana llama
hitTest:withEvent:
a la vista superior de la jerarquía de vistas; Este método se realiza recurriendo recursivamentepointInside:withEvent:
a cada vista en la jerarquía de vistas que devuelve SÍ, avanzando hacia abajo hasta encontrar la subvista dentro de cuyos límites se produjo el toque. Esa vista se convierte en la vista de prueba de impacto.
Entonces, ¿es así que solo hitTest:withEvent:
el sistema llama a la vista superior, que llama pointInside:withEvent:
a todas las subvistas, y si el retorno de una subvista específica es SÍ, entonces llama a pointInside:withEvent:
las subclases de esa subvista?
Respuestas:
Parece una pregunta bastante básica. Pero estoy de acuerdo con usted, el documento no es tan claro como otros documentos, así que aquí está mi respuesta.
La implementación de
hitTest:withEvent:
en UIResponder hace lo siguiente:pointInside:withEvent:
deself
hitTest:withEvent:
regresanil
. El fin de la historia.hitTest:withEvent:
respuesta es SÍ, envía mensajes a sus subvistas. comienza desde la subvista de nivel superior y continúa a otras vistas hasta que una subvista devuelve un nonil
objeto, o todas las subvistas reciben el mensaje.nil
objeto la primera vez, la primerahitTest:withEvent:
devuelve ese objeto. El fin de la historia.nil
objeto, la primerahitTest:withEvent:
devuelveself
Este proceso se repite de forma recursiva, por lo que normalmente se devuelve la vista de hoja de la jerarquía de vistas.
Sin embargo, puede anular
hitTest:withEvent
hacer algo diferente. En muchos casos, la anulaciónpointInside:withEvent:
es más simple y aún ofrece suficientes opciones para modificar el manejo de eventos en su aplicación.fuente
hitTest:withEvent:
todas las subvistas se ejecutan eventualmente?hitTest:withEvent:
sus vistas (ypointInside
si lo desea), imprima un registro y llame[super hitTest...
para averiguar quiénhitTest:withEvent:
se llama en qué orden.Creo que estás confundiendo las subclases con la jerarquía de vistas. Lo que dice el documento es lo siguiente. Digamos que tiene esta jerarquía de vistas. Por jerarquía no estoy hablando de jerarquía de clases, sino de vistas dentro de la jerarquía de vistas, de la siguiente manera:
Digamos que pones tu dedo adentro
D
. Esto es lo que sucederá:hitTest:withEvent:
se llamaA
, la vista superior de la jerarquía de vistas.pointInside:withEvent:
se llama recursivamente en cada vista.pointInside:withEvent:
se llamaA
y devuelveYES
pointInside:withEvent:
se llamaB
y devuelveNO
pointInside:withEvent:
se llamaC
y devuelveYES
pointInside:withEvent:
se llamaD
y devuelveYES
YES
, mirará hacia abajo en la jerarquía para ver la subvista donde tuvo lugar el contacto. En este caso, desdeA
,C
yD
, seráD
.D
será la vista de prueba de éxitofuente
hitTest:withEvent:
B, C y D también se invocan. ¿Qué sucede si D es una subvista de C, no A? Creo que se confundió ...A
volverYES
, así, del mismo modoC
, yD
lo hace?Encuentro que este Hit-Testing en iOS es muy útil
Editar Swift 4:
fuente
Gracias por las respuestas, me ayudaron a resolver situaciones con vistas de "superposición".
Asumir
X
: toque del usuario.pointInside:withEvent:
enB
devolucionesNO
, por lo quehitTest:withEvent:
vuelveA
. Escribí la categoríaUIView
para manejar el problema cuando necesita recibir un toque en la vista superior más visible .userInteractionEnabled
set toNO
;self
,self
se considerará como resultado potencial.Tenga en cuenta que era
[self.subviewsreverseObjectEnumerator]
necesario seguir la jerarquía de vistas de arriba hacia abajo. Y compruebe paraclipsToBounds
asegurarse de no probar subvistas enmascaradas.Uso:
hitTest:withEvent:
con estoLa Guía oficial de Apple también ofrece algunas buenas ilustraciones.
Espero que esto ayude a alguien.
fuente
¡Se muestra como este fragmento!
fuente
El fragmento de @lion funciona a las mil maravillas. Lo porté a Swift 2.1 y lo usé como una extensión de UIView. Lo estoy publicando aquí en caso de que alguien lo necesite.
Para usarlo, simplemente anule hitTest: point: withEvent en su uiview de la siguiente manera:
fuente
Diagrama de clase
Prueba de golpe
Encontrar un
First Responder
First Responder
en este caso es elUIView
point()
método más profundo de los cuales devuelve verdaderoInternamente se
hitTest()
ve comoEnviar evento táctil al
First Responder
Veamos un ejemplo.
Cadena de respuesta
Mira el ejemplo
[Android onTouch]
fuente