¿De qué sirve comprender el mecanismo de ejecución de iOS?
Runloop es la implementación del mecanismo de recepción y distribución de eventos.
Runloop proporciona un mecanismo para ejecutar código de forma asincrónica y no puede ejecutar tareas en paralelo.
En la cola principal, el RunLoop principal coopera directamente con la ejecución de tareas y es responsable de procesar eventos de UI, temporizadores y otros eventos relacionados con el kernel.
(1) El objetivo principal de runloop es:
Asegurar que el sistema no finalice el hilo que ejecuta el programa.
(2). ¿Cuándo utilizar Runloop?
Runloop sólo se utiliza cuando se requiere interacción con hilos.
Cada subproceso tiene un RunLoop correspondiente, pero los RunLoops de subprocesos no principales no se ejecutan de forma predeterminada. Debe agregar al menos una fuente de eventos a RunLoop y luego ejecutarlo.
En circunstancias normales, no necesitamos habilitar el RunLoop del hilo a menos que necesitemos detectar eventos en un hilo separado durante mucho tiempo.
Por defecto, el hilo principal tiene un Runloop. Cuando inicia un hilo, si solo se usa para manejar un único evento, el hilo saldrá después de la ejecución. Entonces, cuando necesitamos dejar que un hilo escuche una transacción.
Runloop es uno de esos bucles. Cuando no hay ningún evento, se queda estancado. Cuando llega un evento, ejecuta la función correspondiente.
RunLoop, como su nombre indica, es donde entran los subprocesos y son utilizados por los subprocesos para responder a eventos y llamar a los controladores de eventos. Las declaraciones de control deben usarse en el código para implementar el bucle RunLoop, es decir, el código debe proporcionar un bucle while o for para controlar RunLoop.
En este bucle, utilice un objeto runLoop [desbloqueo actual de NSRunloop] para recibir mensajes y llamar a la función de procesamiento correspondiente.
Runloop recibe eventos de dos fuentes: fuente de entrada y fuente del temporizador.
Las fuentes de entrada entregan eventos asincrónicos, generalmente mensajes de otros hilos y diferentes programas.
Las fuentes de temporizador (temporizadores) proporcionan eventos sincrónicos (ejecución repetida o activada en un momento específico).
Además de procesar fuentes de entrada, Runloop
también genera algunas notificaciones sobre sus propias acciones. Al registrarse como observador de Runloop, puede recibir estas notificaciones y realizar un trabajo adicional.
Procesamiento. (Utilice CoreFoundation como observador del runloop).
Características del trabajo en bucle en ejecución:
1 gt; Cuando haya tiempo, Runloop notificará a la aplicación según tipos de eventos específicos.
2 gtCuando no hay ningún evento, Runloop entrará en estado de suspensión para ahorrar energía.
3 gtCuando el evento vuelva a ocurrir, Runloop se despertará nuevamente para procesar el evento; .
Consejo: Los Runloops rara vez se crean activamente durante el desarrollo, pero generalmente se agregan eventos a los Runloops.
Dos. Runtime:
Runtime es la abreviatura de RunTime. Es algún mecanismo cuando el sistema se está ejecutando, el más importante de los cuales es el mecanismo de mensajes. Para el lenguaje C, la llamada a la función determinará qué función se llama en el momento de la compilación (
Para llamadas a funciones en lenguaje C, consulte aquí.
). Después de la compilación, se ejecutan directamente en secuencia sin ninguna ambigüedad. La llamada a función del OC se convierte en envío de mensajes. Este es un proceso de llamada dinámico. En tiempo de compilación, no puede decidir qué función llamar (resulta que en tiempo de compilación, durante la fase de traducción, OC puede llamar a cualquier función, incluso si la función no está implementada, siempre que esté declarada, no se producirá ningún error). El lenguaje C informará un error durante la etapa de compilación). La búsqueda se realiza basándose en el nombre de la función sólo cuando realmente se ejecuta.
A la función correspondiente.
Entonces, ¿cómo implementa OC las llamadas dinámicas? Echemos un vistazo al secreto de las llamadas dinámicas de OC mediante el envío de mensajes. Supongamos que escribiste este fragmento de código en OC:
[objc]¿Ver plano?
ltspan style = "tamaño de fuente: 18px;" gt[obj make text];
Donde obj es el objeto y makeText es el nombre de la función. Una llamada telefónica tan sencilla. En tiempo de compilación, el tiempo de ejecución convertirá el código anterior en
[objc]¿Ver plano?
objc_msgSend(obj, @selector(makeText));
Primero echemos un vistazo al objeto obj, que se hereda de NSObject en iOS.
[objc]¿Ver la llanura?
@ interfaz NSObject ltnsobject gt{
isa OBJC_ISA_AVAILABILITY class;
} lt/n object gt
Hay una clase en NSObjcet es un puntero. Entonces veamos las clases:
[objc]¿Ver plano?
typedef struct objc _ class * Clase
Estructura object_class {
isa class //apunta a metaclase
Clase super _ class; // Apunta a su clase principal
const charchar * name//Nombre de clase
Versión larga // La información de versión de la clase se inicializa a 0 de forma predeterminada y se puede pasar; a través del tiempo de ejecución Las funciones class_setVersion y class_getVersion se utilizan para modificar y leer.
Información larga; // Alguna información de identificación, como CLS_CLASS (0x1L), indica que esta clase es una clase normal, incluidos métodos de objeto y variables miembro. CLS_META (0x2L) indica que la clase es una metaclase; , incluidos los métodos de clase;
longstance_size//El tamaño de las variables de instancia de esta clase (incluidas las variables de instancia heredadas de la clase principal
struct objc _ivar _); list * ivars//usado para almacenamiento La dirección de cada variable miembro.
struct objc _ método _ lista * * lista de métodos; // Relacionado con algunos indicadores de información, como CLS_CLASS (0x1L), luego almacena los métodos de objeto, como CLS_META (0x2L), y luego almacena la clase. métodos;
struct objc _ cache * cache//Puntero al método utilizado recientemente para mejorar la eficiencia
struct objc _ protocolo _ list *protocolo; la clase se adhiere a .
}
Podemos ver que hay muchas cosas en una clase. Déjame explicarlas una por una:
Clase
Isa: apunta a la metaclase, que es una clase estática. Por lo general, isa en el objeto Obj apunta a una clase ordinaria que almacena variables miembro ordinarias y pares de miembros.
Al igual que los métodos (métodos que comienzan con "-"), el puntero isa en una clase normal apunta a una clase estática, que almacena variables miembro de tipo estático y métodos de clase (métodos que comienzan con "")
p>Francia).
Apunta a la clase principal. Si esta clase es la clase raíz, estará vacía.
La siguiente figura describe bien la relación de herencia entre clases y objetos:
Nota: todos los punteros isa en metaclases apuntan a metaclases.
En la metaclase, apunta a sí mismo.
La metaclase raíz se genera heredando la clase raíz. Consistente con los miembros de la estructura de clases raíz, que es la estructura mencionada anteriormente. La diferencia es la raíz.
El puntero isa de la metaclase apunta a sí mismo.