Colección de citas famosas - Slogan de motivación - Comprensión del tiempo de ejecución de IOS

Comprensión del tiempo de ejecución de IOS

Runtime

Descripción general: runtime, también llamado runtime, es un conjunto de API de lenguaje C de bajo nivel y es uno de los núcleos del sistema iOS. Un desarrollador puede enviar un mensaje a cualquier objeto durante la codificación, pero solo durante la fase de compilación decide enviar el mensaje al receptor. La forma en que el receptor responde y maneja el mensaje depende del tiempo de ejecución.

? En lenguaje C, el compilador decide qué función llamar, mientras que las funciones de OC pertenecen a un proceso de llamada dinámica. El compilador realmente no puede decidir qué función llamar. Solo cuando se esté ejecutando realmente encontrará la función correspondiente según el nombre de la función. y llámalo. OC es un lenguaje dinámico, lo que significa que requiere no solo un compilador, sino también un sistema de ejecución para crear clases y objetos dinámicamente, pasar y enviar mensajes.

1. Reenvío de mensajes

La función principal de la biblioteca en tiempo de ejecución es el paso de mensajes. Si el mensaje no se encuentra en el objeto, será reenviado. Objective-C es un lenguaje dinámico, lo que significa que requiere no sólo un compilador, sino también un sistema de ejecución para crear dinámicamente clases y objetos, y para pasar y reenviar mensajes. El núcleo del tiempo de ejecución es el paso de mensajes.

(1) El proceso de paso de mensajes

El método de un objeto [obj test], el compilador lo convierte en un mensaje y lo envía objc _ msgsend (obj, test) , que se ejecuta en tiempo de ejecución. El proceso es el siguiente.

A. Primero encuentre su clase a través del puntero isa de obj.

B. Busque la prueba en la lista de métodos de la clase.

Si la prueba no se encuentra en la clase, continúe buscándola en su superclase.

D. Una vez encontrada una prueba de función, ejecute su IMP.

Debido a problemas de eficiencia, no es razonable recorrer objc_method_list una vez para cada mensaje, por lo que las funciones llamadas con frecuencia deben almacenarse en caché para mejorar la eficiencia de la consulta de funciones. Esta es la función de objc_cache, otro miembro importante de objc_class. Una vez que encuentre la prueba, use el nombre_método de la prueba como clave y método_imp como valor. Cuando reciba el mensaje de prueba nuevamente, podrá buscarlo directamente en el caché.

Objeto de clase (objc_class)

Las clases de Objective-C están representadas por tipos de clase, que en realidad son punteros a estructuras objc_class. Hay muchas variables definidas en la estructura struct objc_class. El puntero a la clase principal, el nombre de la clase, la versión, la lista de variables de instancia (ivars), la lista de métodos (caché) y la lista de protocolos (protocolos) se almacenan en esta estructura. De esta manera, un objeto de clase es una estructura struct objc_class y los datos almacenados en esta estructura son metadatos.

Comprender el tiempo de ejecución significa comprender el almacenamiento de datos de iOS y las relaciones y funciones entre sus clases, instancias, objetos de clase y metaclases.

(2) Mecanismo de reenvío de mensajes

En el análisis final, la esencia de todas las llamadas a métodos en Objective-C es enviar mensajes a objetos.

1. Crear un método en prueba de clase (void)

2.2 El sistema iOS crea un número SEL(prueba) para este método y lo agrega a la lista de métodos.

3. Cuando se llama al método, el sistema busca el método en la lista de métodos y lo ejecuta cuando lo encuentra.

Así que llamar a un método enviará un mensaje una vez, que se encontrará en la lista de métodos de esta clase. Si no se encuentra en esta clase, se encontrará en la clase principal de esta clase. Si aún no se encuentra la clase principal, se busca en la raíz del árbol de herencia. Si no se encuentra o el reenvío del mensaje no tiene éxito, se informará un error de selector no reconocido.

1. Análisis de métodos dinámicos

El tiempo de ejecución de Objective-C llamará a resolveInstanceMethod: ¿o? resolveClassMethod: le brinda la oportunidad de proporcionar una implementación de función.

Si agrega una función y devuelve SÍ, el tiempo de ejecución reiniciará el proceso de envío de mensajes. Como se muestra en la siguiente figura:

Aunque no existe una función de implementación de foo:, la función fooMethod se agrega dinámicamente a través de class_addMethod() y la ejecución de la función se imprime correctamente. Si reslove devuelve NO, el tiempo de ejecución ingresará al siguiente paso: forwardingTargetSelector.

2. Reenvío directo de mensajes

Si el objeto de destino implementa forwardingTargetSelector, el tiempo de ejecución llamará a este método en este momento, brindándole la oportunidad de reenviar este mensaje a otros objetos.

Como se puede ver en la imagen, pasamos el método de la clase actual a la clase principal a través del método forwardingTargetForSelector y la impresión se realizó correctamente.

3. Reenvío completo de mensajes

Si el mensaje desconocido no se puede procesar en el paso anterior, lo único que se puede hacer es iniciar el mecanismo de reenvío de mensajes. Primero, envía un mensaje MethodSignatureForSelector para obtener el parámetro de la función y los tipos de valor de retorno. Si métodoSignatureForSelector devuelve cero, el tiempo de ejecución emitirá didNotRecognizeSelector. Si se devuelve una función firmada, el tiempo de ejecución creará un objeto NSInvocation y enviará un mensaje forwardInvocation al objeto de destino.

Aplicación práctica del tiempo de ejecución

1. Utilice el método de intercambio de tiempo de ejecución

2. Método de adición dinámica (aún no se comprende bien)

3. 4. Agregar atributos a las categorías

4. Reenvío de mensajes (actualización en caliente) para resolver errores (JSPatch)

.