Carga de clases de iOS (Parte 2)
En el artículo anterior Carga de clases (Parte 1), entendimos cómo se cargan las clases en la memoria desde Mach-O. Esta vez explicaremos cómo se cargan las categorías en las clases y el uso de la clasificación y las clases.
Requisito previo: definir la clasificación LG de LGperson en principal
Método 1: mediante clang
Al mismo tiempo, descubrimos un problema: verifique _prop_list_t. que los atributos están definidos en la clasificación, pero los atributos no se ven en la compilación subyacente, como se muestra en la figura siguiente. Esto se debe a que los atributos definidos en la clasificación no tienen los métodos set y get correspondientes. Podemos asociar objetos a través. Para configurar (sobre cómo configurar el objeto asociado, lo explicaremos en la siguiente expansión)
Método 3: buscar categoría_t a través del código fuente objc
En resumen, la esencia de la clasificación es un tipo _category_t
Requisito previo: crear dos categorías de LGPerson: LGA, LGB
En la carga de clases anterior (Parte 1) realiceClassWithoutSwift -> metodizeClass -> adjuntarToClass en el artículo -> load_categories_nolock -> extAlloc ->attachCategories menciona la carga de rwe, que analiza cómo se cargan los datos clasificados en la clase, y el orden de carga de las categorías es: LGA -> LGB se carga en la clase en orden, es decir, el más tarde se agrega, cuanto antes se agrega
Al observar la implementación del código fuente de MethodClass, se puede encontrar que los datos de clase y los datos de clasificación se procesan por separado, principalmente porque el método se ha determinado durante el proceso. etapa de compilación ubicación de atribución (es decir, los métodos de instancia se almacenan en clases, los métodos de clase se almacenan en metaclases) y la clasificación se agrega más tarde
Entre ellos, la clasificación debe agregarse a la clase a través de addToClass antes. se puede realizar fuera En este proceso, ya conocemos los dos últimos pasos de los tres pasos de la carga de clasificación se divide principalmente en tres pasos:
Exploremos el tiempo de carga de datos clasificados, utilizando. la clase principal LGPerson + Clasificación LGA y LGB implementan el método +load como ejemplo
Invertir el tiempo de carga del primer paso al segundo paso de preparación de datos
addT
En el método oClass, se descubrió mediante depuración que nunca ingresa al proceso if. A menos que se cargue dos veces, las clases ordinarias generalmente solo se cargan una vez
Búsqueda global de llamadas load_categories_nolock, hay dos llamadas
p> p>A través del análisis de información de la pila
Entonces, en resumen, la ruta inversa del tiempo de carga de los datos de clasificación en este caso es: adjuntoCategories -> load_categories_nolock -> loadAllCategories -> load_images
La ruta de nuestro proceso normal de carga de categorías es: realizarClassWithoutSwift -> metodizeClass -> adjuntarToClase ->attachCategories
Los procesos directo e inverso se muestran en la siguiente figura:
Veamos otra situación: clase principal + categoría LGA implementa +carga, categoría LGB no implementa el método +carga
Resumen: siempre que una categoría sea una categoría de carga no diferida, entonces todas las categorías será El bit de marca es una clasificación de carga no diferida, lo que significa que después de cargar una vez y abrir rwe, no se volverá a cargar de forma diferida y procesará LGPerson nuevamente
A través de los dos ejemplos anteriores, podemos aproximadamente determine si la clase y la clasificación están implementadas La situación de carga se divide en 4 tipos Es decir, la clase principal implementa el método de carga y la clasificación también implementa el método de carga que ya hemos analizado. esta situación en el tiempo de carga de la clasificación anterior, por lo que podemos sacar directamente la conclusión de que en este caso
la ruta de llamada es:
Es decir, la clase principal implementa el + método de carga, y la clasificación no implementa el método +load
Como se puede ver en la impresión anterior, el orden de los métodos es la clase LGB-LGA-LGPerson. En este momento, la clasificación tiene. se ha cargado, pero no se ha ordenado. Esto significa que cuando no se realiza una carga no diferida, Mach se lee a través de cls->-datos, los datos ya se han compilado y no es necesario agregarlos. en tiempo de ejecución* Vaya a la parte del punto de interrupción del método MethodClass
Vaya a la parte del bucle for de prepareMethodLists
Vaya a la parte if (sort) { del método fixupMethodList
Vaya a mlist->setFixedUp() ;, después de leer la lista
, al imprimir se descubre que solo los métodos con el mismo nombre están ordenados, mientras que otros métodos en la categoría no necesitan ordenarse. Las otras direcciones imp están ordenadas. de pequeño a grande) - La clasificación en fixupMethodList solo ordena la dirección del nombre
Resumen: la carga de datos de clases de carga no diferida y categorías de carga diferida tiene las siguientes conclusiones:
Es decir , no se implementa ni la clase principal ni la clasificación. + método de carga
Resumen: la carga de datos de las clases de carga diferida y las categorías de carga diferida se registra cuando se llama al mensaje por primera vez
Es decir, la clase principal no implementa el método +load, pero el método +load sí lo hace
Resumen: clase de carga diferida + carga de datos de categoría de carga no diferida, siempre que la categoría. Al implementar la carga, la clase principal se verá obligada a cargarse por adelantado, es decir, la clase principal se convertirá a la fuerza a un estilo de clase de carga no diferida p>
Las clases y categorías se usan juntas, y la carga de datos El tiempo se resume de la siguiente manera:
Como se muestra en la siguiente figura
La función principal del método load_images es cargar archivos de imagen, el más importante de los cuales Hay dos métodos: prepare_load_methods (cargando) y call_load_methods (llamada)
Ingrese el código fuente de prepare_load_methods
Ingrese el código fuente call_load_methods, hay principalmente tres partes de la operación
En resumen, el proceso de llamada general y el principio del método load_images son los siguientes
Se divide principalmente en dos pasos