Colección de citas famosas - Colección de consignas - ¿Por qué la clasificación no puede agregar variables miembro?

¿Por qué la clasificación no puede agregar variables miembro?

La propiedad es la propiedad y e Ivar es la variable miembro.

De hecho, puedes agregar atributos a una clase en clasificación, pero no puedes agregar variables miembro. No confunda los conceptos de variables miembro y propiedades.

Xcode no genera automáticamente variables miembro subrayadas ni conjuntos de categorías ni métodos de obtención al agregar propiedades. Si no implementa estos dos métodos manualmente, llamar a esta propiedad mediante la sintaxis de puntos definitivamente se bloqueará directamente y el selector no reconocido se enviará a la instancia, porque no tiene estos dos métodos en absoluto. Entonces, cuando realmente declaras un atributo en una clasificación, debes implementar manualmente los métodos set y get de este atributo. En este momento, debe utilizar el mecanismo de tiempo de ejecución para asociar el proceso de acceso de esta propiedad.

Entonces, ¿por qué no agregar variables miembro a la clasificación?

Las variables miembro son una especie de cosa y la clasificación en sí no es una clase. La clasificación son originalmente algunos métodos y atributos que se agregan dinámicamente a una clase en OC en tiempo de ejecución y no son una clase real. ¿Cómo agregarle variables miembro?

Ivar no se puede agregar a una clasificación porque la clasificación en sí no es una clase real, no tiene su propia ISA. Al principio, la clase genera muchas propiedades básicas como IvarList y MethodList. La clasificación solo adjuntará sus propios métodos a la clase principal y no afectará la IvarList de la clase principal. Es por eso que las variables miembro no se pueden agregar a las categorías.

¿Por qué no puedo agregar variables miembro?

Las clases de Objective-C están representadas por tipos de clase, que en realidad son punteros a estructuras objc_class. Su definición es la siguiente:

typedef struct objc_class * Class

La definición de la estructura objc_class es la siguiente:

structobjc_class{Class isa? OBJC_ISA_DISPONIBILIDAD#SI! __OBJC2__Clase super_clase? OBJC2 _ No disponible; // Clase principal const char * nombre objc 2 _ no disponible; // Nombre de clase versión larga OBJC2 _ NO DISPONIBLE // Información de la versión de la clase, ¿el valor predeterminado es 0longinfo? OBJC2 _No disponible; //Información de clase, ¿algunos bits que identifican longinstance_size en tiempo de ejecución? OBJC2 _ Unavailable; // El tamaño de la variable de instancia de esta clase es struct objc _ ivar _ list * ivarsobjc 2 _ unavailable; // La lista de variables miembro de esta clase struct objc _ método _ list * * metodlistsobjc 2 _ unavailable; //Método de lista vinculada definida struct objc _ cache * cache objc 2 _ unavailable; //Método de caché structo bjc _ protocolo _ list * protocolo bjc 2 _ no disponible // Lista vinculada de protocolo # endif } OBJC2 _ UNAVAILABLE

<; p>En lo anterior En la estructura objc_class, ivars es un puntero objc_ivar_list (lista de variables miembro); MethodLists es un puntero al puntero objc_method_list; En tiempo de ejecución, el tamaño de la estructura objc_class es fijo, por lo que no se pueden agregar datos a la estructura, solo modificarlos. Por lo tanto, ivars se refiere a un área fija. Solo puede modificar los valores de las variables miembro, pero no puede aumentar el número de variables miembro. MethodList es una matriz bidimensional, por lo que el valor de *methodLists se puede modificar para agregar métodos miembro. Aunque el área de memoria a la que apuntan las listas de métodos no se puede ampliar, el valor de esta área de memoria (puntero de almacenamiento) se puede cambiar.

Por lo tanto, los métodos se pueden agregar dinámicamente, pero no se pueden agregar variables miembro.

Entre las funciones de tiempo de ejecución proporcionadas por Objective-C, existe de hecho una función class_addIvar() para agregar variables miembro a la clase, pero el documento establece específicamente:

Esta función solo puede se llamará después de objc_allocateClassPair y antes de objc_registerClassPair. No se admite agregar variables de instancia a clases existentes.

Esto significa que esta función sólo puede ser llamada "durante la construcción de la clase". Una vez que se completa la definición de la clase, no puede agregar variables miembro. La biblioteca en tiempo de ejecución carga la clase compilada después de que se inicia el programa y no hay posibilidad de llamar a addIvar. Las clases construidas dinámicamente por el programa durante el tiempo de ejecución solo se pueden usar después de llamar a objc_allocateClassPair y antes de objc_registerClassPair. No hay posibilidad de agregar variables miembro.

La categoría no puede agregar variables de instancia, entonces, ¿se pueden agregar atributos?

Debemos comenzar con la estructura de la categoría:

typedefstructcategory _ t { const char * name; classref _ nombre de la clase tcls // class struct método _ list _ t; * métodos de instancia; // Una lista de todos los métodos de instancia agregados a esta clase en // categoría método de estructura _ Lista _ t * métodos de clase // Una lista de todos los métodos de clase agregados en la categoría struct protocolo _ lista _ t * protocolos; // categoría estructura propiedad _ lista _ t * lista de todos los protocolos implementados por las propiedades de la instancia; categoría } categoría _ todas las propiedades agregadas en t

También se puede ver en la definición de Categoría que Categoría puede ser; (Se pueden agregar métodos de instancia, métodos de clase, incluso implementar protocolos, agregar propiedades) y no se puede (no se pueden agregar variables de instancia).

Entonces, ¿por qué escuchamos a menudo que los atributos no se pueden agregar a las categorías? De hecho, la categoría en realidad permite agregar atributos. También puede usar @property, pero no generará variables _ (variables miembro subrayadas), ni generará métodos getter y setter para agregar atributos. Entonces, aunque se agregan las propiedades, no es posible llamar a los métodos getter y setter usando la sintaxis de puntos. Si quieres realizar la función de tus atributos habituales, ¿qué debes hacer?

De hecho, podemos usar el tiempo de ejecución para implementarlo, usar el tiempo de ejecución para implementar Categoría, agregar nuevas propiedades a las clases existentes y generar métodos getter y setter. No olvide que Objective-C es un lenguaje dinámico. El método consiste en acceder y generar objetos relacionados en tiempo de ejecución a través de objc_get objeto asociado/objc_set objeto asociado h. Estos dos métodos pueden asociar un objeto con otro objeto, es decir, un objeto puede mantener el acceso a otro objeto y obtener ese objeto. .

//ns object+nombre de banda independiente. h @ interfaceNSObject(nombre de banda independiente)@ propiedad (nonatomic, strong)ns string * nombre de banda independiente @end

Lo anterior es el archivo de encabezado; declaración, Aquí está.

m file:

//ns object+nombre de banda independiente . m # import " ns object+extension . h " # importstaticconstvoid * clave de nombre de banda independiente = &IndieBandNameKey@implementationNSObject(nombre de banda independiente)@dynamicindieBandName;- ( ns string *)nombre de banda independiente { return objc _ getAssociatedObject (self, clave de nombre de banda independiente } - (void) setIndieBandName: (ns string *) IndieBandName { OBJC _ setassociated object (self, IndieBandNameKey, nombre de banda independiente, OBJC _ ASSOCIATION _ RETAIN_NONATOMIC );} @End

Las variables de instancia se pueden agregar a una categoría de dos maneras en tiempo de ejecución.