La Red de Conocimientos Pedagógicos - Conocimientos históricos - Mecanismo de respuesta y entrega de eventos

Mecanismo de respuesta y entrega de eventos

Objeto de respuesta

En iOS, ningún objeto puede manejar eventos. Sólo los objetos que heredan UIResponder pueden aceptar y procesar eventos. Los llamamos "objetos de respuesta". Por ejemplo, los más comunes: UIApplication ? UIViewController ? UIView

UIResponder puede manejar eventos táctiles, eventos de prensa (3D touch), eventos de control remoto y eventos de movimiento de hardware.

Entrega de eventos

1. Después de que ocurre un evento táctil, el sistema agregará el evento a una cola de eventos administrada por UIApplication. Debido a que la cola se caracteriza por FIFO, es decir, primero en entrar, primero en salir, el evento generado primero se procesa primero (UIApplication es el primero en recibir el evento).

2. UIApplication sacará el evento frontal de la cola de eventos y lo distribuirá para su procesamiento. Por lo general, primero envía el evento a la ventana principal (keyWindow) de la aplicación.

3. La ventana principal encontrará la vista más apropiada en la jerarquía de vistas para manejar el evento táctil. Después de encontrar el control de vista apropiado, se llamará al método de toques del control de vista para el procesamiento de eventos específicos.

El evento táctil se pasa del control principal al control secundario: ?UIApplication-gt; ventana-gt; encuentre la vista más adecuada para manejar el evento

UIView no puede recibir toque. eventos 4 Casos:

1. No se permite la interacción: userInteractionEnabled = NO, no se puede interactuar con la vista actual y las subvistas encima de esta vista no pueden interactuar con el usuario. La vista ignorará los eventos desencadenados por el usuario (otras vistas responden como de costumbre) y el objeto de la vista también se eliminará de la cola de respuesta de eventos.

2. Oculto: Si el control padre está oculto, el control hijo también estará oculto y el control oculto no puede recibir eventos

3. Transparencia: Si la transparencia de un control se establece <0.01, afectará directamente la transparencia del control secundario. alfa: 0,0~0,01 es transparente.

4. Si parte de la subvista excede la vista principal, no recibirá eventos táctiles porque la vista principal devolverá NO al llamar al método pointInside. Significa que el punto de contacto no está dentro de su propio rango, entonces el método hitTest de la vista actual: withEvent: devuelve nulo y no se juzgan todas las subvistas de la vista actual.

Nota: Si la posición Touch excede los límites de la vista, el método hitTest:withEvent ignorará esta vista y todas sus subvistas. El resultado es que cuando la propiedad ciipsToBounds de la vista es NO, la subvista no recibirá eventos más allá de los límites de la vista, incluso si el punto de contacto está en ella.

Independientemente de si la vista puede manejar el evento, siempre que se haga clic en la vista, se generará un evento. La clave está en quién manejará el evento al final. El sistema utiliza hitTest: (CGPoint)point withEvent: (UIEvent*)incluso para encontrar la vista más adecuada para manejar el evento.

¿Cómo encuentra la aplicación el control más apropiado para manejar el evento?

1. Primero determine si la ventana principal (keyWindow) puede aceptar eventos táctiles usando el método hitTest.

2. Determine si el punto de contacto está en usted mismo mediante el método pointInside.

3. Si se cumplen las condiciones de los dos pasos anteriores, el evento se entregará a la vista para su procesamiento y los datos de subcontrol de las subvistas de la vista se recorrerán hasta que no haya más. vista adecuada.

Nota: recorra los controles secundarios desde el final de la matriz hacia adelante, porque la vista agregada más tarde está en la parte superior y el respondedor superior puede recibir la respuesta primero, bloqueando el evento para que no continúe pasando, por lo tanto reduciendo el número de bucles de iteración.

5. Si no hay un control infantil que cumpla las condiciones, entonces crees que eres el más adecuado para manejar este evento y regresar a ti mismo.

¿Está buscando la vista más adecuada para el análisis subyacente? Dos métodos importantes:

Escenarios de uso del método Piontinside: IOS aumenta el área de clic del botón - aumenta el área de respuesta al clic del botón - (UIView * )hitTest: (CGPoint)point withEvent: (UIEvent*)event? ¿Cuándo se llama?

?Se llamará a quien se pase el evento cuyo método hitTest:withEvent: se llame.

Función

Encuentra y devuelve la vista más adecuada que pueda responder al evento No importa dónde haga clic, la vista más adecuada es la vista devuelta en el método hitTest.

Nota: No importa si este control puede manejar el evento o si el punto de contacto está en este control, el evento se pasará primero a este control y se llamará al método hitTest para determinar si el El evento puede ser procesado.

Procesamiento de eventos de interceptación

¿Devuelve la vista especificada anulando el método hitTest? Puede interceptar el proceso de entrega del evento y quien quiera que maneje el evento puede manejarlo.

Nota: Si se devuelve nil en el método hitTest?, entonces ni el control en sí ni sus subcontroles que llaman a este método son la vista más adecuada, es decir, no se ha encontrado ninguna vista más adecuada. sí mismo. Si otros controles en el mismo nivel no tienen una vista adecuada, la vista más adecuada es el control principal.

Independientemente de si el control secundario es la vista más adecuada, el sistema pasa de forma predeterminada el evento al control secundario primero, y el control secundario sabrá si hay una vista más adecuada después de llamar a su propio hitTest. :withEvent: método. Incluso si el control principal es la vista más adecuada, se seguirá llamando al método hitTest:withEvent: del control secundario.

Consejo: ¿Quien quiera que sea la vista más adecuada, reescriba el hitTest del control principal: withEvent: método para devolver el control secundario especificado, o reescriba su propio hitTest: withEvent: método para devolver self? . Sin embargo, se recomienda devolver el control secundario como la vista más apropiada en hitTest:withEvent: del control principal.

¿El motivo: al atravesar el control secundario, si el punto de contacto no está en el niño? control A en sí, pero en el control secundario. Para el control B, si desea devolver el subcontrol A como la vista más apropiada, usar el método de regresar a sí mismo puede llevar al hecho de que la vista real B haya sido atravesada antes que A. tiempo para recorrer. Esto da como resultado que no regrese a sí mismo sino a la vista donde realmente se encuentra el punto de contacto. Por lo tanto, se recomienda devolver el control secundario como la vista más apropiada en hitTest:withEvent: del control principal.

Después de encontrar la vista más adecuada, se llamará al método touchs de la vista para manejar eventos específicos.

¿Cómo pasar eventos táctiles a la aplicación actual después de que sean generados por la pantalla táctil?

Fase de respuesta del sistema

Cuando el usuario toca la pantalla, el proceso de hardware del sistema obtendrá el evento de clic, simplemente procesará y encapsulará el evento y lo almacenará en el sistema. El proceso de detección de hardware y el proceso de aplicación actual Hay dos procesos, por lo que la comunicación por puerto se utiliza para transferir eventos entre los dos procesos.

1. Toque la pantalla Después de que la pantalla detecta el toque, el evento se entrega a IOKit para su procesamiento.

2. IOKit encapsula el evento táctil en un objeto IOHIDEvent y lo pasa al proceso SpringBoad a través del puerto mach. puerto mach puerto de proceso, a través del cual se comunican los procesos.

3. SpringBoad es un proceso del sistema que gestiona y distribuye uniformemente los eventos táctiles recibidos por el sistema. Maneje eventos táctiles en el proceso de la aplicación en primer plano para su procesamiento.

Referencia: Aprendizaje del principio RunLoop -

Fase de respuesta de la APP

1. El puerto mach del proceso APP recibe el evento táctil pasado por el proceso SpringBoard y el hilo principal Se activa el runloop y se activa la devolución de llamada source1.

2. La devolución de llamada de fuente1 activa una devolución de llamada de fuente0, que encapsula el objeto IOHIDEvent recibido en un objeto UIEvent.

3. La devolución de llamada source0 agrega internamente el evento táctil a la cola de eventos del objeto UIApplication. Una vez que el evento se retira de la cola, UIApplication comienza a buscar el mejor respondedor. Este proceso también se denomina prueba de aciertos. ?

3. El sistema determina si este toque provocó un nuevo evento. Si es así, el sistema primero buscará la cadena de respuesta en la red de respuesta. De lo contrario, significa que el evento es un mensaje táctil generado por el evento actualmente en curso, lo que significa que ya existe una cadena de respuesta guardada

4. Después de encontrar al mejor respondedor, el evento responde Entrega y respuesta en la cadena.

Cadena de respuesta: una cadena conectada por múltiples objetos de respuesta

En un programa de iOS, ya sea la UIWindow en la parte posterior o un botón en la parte frontal, su ubicación Hay un contexto Un control se puede colocar encima o debajo de otro control. Cuando el usuario hace clic en un control, ¿activa el control superior o el control inferior? Esta relación secuencial forma una cadena llamada "cadena de respuesta".

Los eventos pasan por la cadena de respuesta y el resultado final es que el evento se procesa o descarta. La cadena de respuesta puede ver claramente la conexión entre cada respuesta y puede permitir que varios objetos manejen un evento.

Cada objeto de respuesta (objeto UIResponder) tiene un método nextResponder, que se utiliza para obtener el siguiente respondedor del objeto actual en la cadena de respuesta. Por lo tanto, una vez que se determina quién es el primero en responder a un incidente, se determina la cadena de respuesta en la que ocurre el incidente.

El nextResponder predeterminado del objeto de respuesta es el siguiente:

1. La propiedad nextResponder de UIView Si hay un objeto UIViewController que administra esta vista, este es 2. UIViewController. objeto; de lo contrario, nextResponder es su supervisión.

3. El atributo nextResponder de UIViewController es la supervista de su vista administrada.

Si VC es la vista raíz rootVC de la ventana, su nextResponder es UIWindow;

Si el VC se presenta desde otro controlador, su nextResponder es el controlador de vista de presentación.

4. La propiedad nextResponder de UIWindow es un objeto UIApplication.

5. La propiedad nextResponder de UIApplication es nula.

Si el delegado de la aplicación actual es un objeto UIResponder y no es UIView, UIViewController o la aplicación en sí, entonces el nextResponder de UIApplication es el delegado de la aplicación. ?

El proceso de entrega de eventos de la cadena de respuesta:

1. ?Si la vista actual es la vista del controlador, entonces el controlador es el respondedor anterior y el evento se pasa a el controlador; si la vista actual no es la vista del controlador, entonces la vista principal es el respondedor anterior de la vista actual y el evento se pasa a su vista principal

2. En la vista de nivel superior de la jerarquía de vistas, si el evento o mensaje recibido no se puede procesar, pasará el evento o mensaje al objeto de ventana para su procesamiento

3. Si el objeto de ventana no puede manejarlo, pasará el evento o mensaje al objeto UIApplication

4. Si UIApplication no puede manejar el evento o mensaje, será descartado

El respondedor tiene tres operaciones para el evento recibido:

1. No interceptar, la operación predeterminada. Los eventos se transmitirán automáticamente a lo largo de la cadena de respuesta predeterminada (el método táctil no procesa eventos de manera predeterminada, solo pasa eventos) y el evento se entregará a el respondedor anterior para su procesamiento.

En UIResponder La implementación predeterminada de UIResponder en UIKit no hace nada, pero la implementación predeterminada de las subclases directas de UIResponder en UIKit (UIView, UIViewController...) es pasar el evento la cadena de respuesta al siguiente respondedor, que es nextResponder.

2. Intercepte, ya no distribuya eventos hacia abajo, reescriba touchesBegan: withEvent: realice el procesamiento de eventos, no llame a touchesBegan: withEvent de la clase principal, el evento finaliza aquí para su procesamiento.

3. Intercepte, continúe distribuyendo eventos hacia abajo, reescriba sus propios toquesBegan: withEvent: para el procesamiento de eventos y llame a [super?touchesBegan: withEvent:] al mismo tiempo para pasar el evento hacia abajo para lograr múltiples eventos para un evento El propósito del manejo de objetos. ?

Se recomienda utilizar: [super touchesBegan: touches withEvent: event] ?

El método correspondiente a los toques de super continuará pasando el evento hacia arriba al siguiente respondedor por por defecto. ?

No se recomienda enviar mensajes directamente a nextResponder, ya que esto puede omitir otro procesamiento de este evento por parte de la clase principal.

[self.nextResponder? touchesBegan: touches withEvent: event];

Los eventos de gestos interrumpirán la entrega de la cadena de respuesta. Debido a que los gestos tienen una prioridad más alta que la cadena de respuesta, la Vista a la que se agrega el gesto evitará que la subvista responda a la cadena, y el gesto responderá primero y manejará el evento. Este evento ya no pasa a la cadena de respuesta.

Cuando _UIApplicationHandleEventQueue() reconoce un gesto, primero llama a Cancelar para interrumpir las devoluciones de llamada de la serie touchesBegin/Move/End actuales. Luego, el sistema marca el UIGestureRecognizer correspondiente como pendiente.

Apple ha registrado un Observer para monitorear el evento BeforeWaiting (Loop está a punto de dormirse). La función de devolución de llamada de este Observer es _UIGestureRecognizerUpdateObserver(), que internamente obtendrá todos los GestureRecognizers que se acaban de marcar. como pendiente y ejecutar la devolución de llamada de GestureRecognizer. Cuando UIGestureRecognizer cambia (crea/destruye/cambia de estado), se procesará la devolución de llamada.

La diferencia entre entrega de eventos y respuesta:

La entrega de eventos es de arriba a abajo (control principal a control secundario) y la respuesta al evento es de abajo hacia arriba (a lo largo del paso de respuesta). arriba en la cadena: control hijo a control padre

Puedes encontrar su control VC correspondiente según una vista:?

Artículo de referencia:

El más detallado en historial de entrega de eventos y mecanismo de respuesta de iOS - Principio -

Respondedor de iOS y cadena de respuesta -

iOS - ¿Por qué deberíamos operar la interfaz de usuario en el hilo principal?