2009-05-11 13 views
18

Traté de enumerar todas las propiedades de una clase Objective-C como se describen en el Objective-C 2.0 Runtime Programming Guide:Objective-C 2.0: class_copyPropertyList(), cómo enumerar las propiedades de las categorías

id LenderClass = objc_getClass("UIView"); 
unsigned int outCount, i; 
objc_property_t *properties = class_copyPropertyList(LenderClass, &outCount); 
for (i = 0; i < outCount; i++) { 
    objc_property_t property = properties[i]; 
    fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property)); 
} 

Sin embargo, esta lista solo tres propiedades:

userInteractionEnabled Tc,GisUserInteractionEnabled 
layer [email protected]"CALayer",R,&,V_layer 
tag Ti,V_tag 

En cuanto al archivo de encabezado para UIView.h esas son las tres propiedades declaradas directamente en la clase. Las otras propiedades de UIView se agregan a través de categorías.

¿Cómo obtengo todas las propiedades de una clase, incluidas las provenientes de categorías?

Probé esto con el simulador de iPhone (iPhone SDK 2.2.1), por cierto. (en caso de que esto sea importante).

+0

Tal vez se declaran como dinámicos y no se sintetizan debido a CALayer? Y por lo tanto, no visible? – hfossli

Respuesta

14

Según mis pruebas aquí, las propiedades de las categorías aparecerán al usar class_copyPropertyList. Parece que las propiedades que está viendo en UIView son solo que se describen como como propiedades en los encabezados públicos, que en realidad no se declaran como tales cuando se construye el UIKit. Probablemente adoptaron la sintaxis de la propiedad para hacer la creación de los encabezados públicos un poco más rápido.

Para referencia, aquí es mi proyecto de prueba:

#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

@interface TestClass : NSObject 
{ 
    NSString * str1; 
    NSString * str2; 
} 
@property (nonatomic, copy) NSString * str1; 
@end 

@interface TestClass (TestCategory) 
@property (nonatomic, copy) NSString * str2; 
@end 

@implementation TestClass 
@synthesize str1; 
@end 

@implementation TestClass (TestCategory) 

// have to actually *implement* these functions, can't use @synthesize for category-based properties 
- (NSString *) str2 
{ 
    return (str2); 
} 

- (void) setStr2: (NSString *) newStr 
{ 
    [str2 release]; 
    str2 = [newStr copy]; 
} 

@end 

int main (int argc, const char * argv[]) 
{ 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    unsigned int outCount, i; 
    objc_property_t *properties = class_copyPropertyList([TestClass class], &outCount); 
    for (i = 0; i < outCount; i++) { 
     objc_property_t property = properties[i]; 
     fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property)); 
    } 

    [pool drain]; 
    return 0; 
} 

Y aquí está la salida:

str2 [email protected]"NSString",C 
str1 [email protected]"NSString",C,Vstr1 
+0

Muchas gracias por la respuesta. Realmente parece que algo es especial sobre el UIKit a este respecto. Pero su ejemplo en realidad no muestra esto ya que funciona como se esperaba; es decir, enumera la propiedad str2 (que es más de lo que obtengo con UIView). – ashcatch

+1

Esto es lo que quise decir, arriba. Las propiedades declaradas en los encabezados públicos para UIView no se declaran realmente como propiedades en la fuente utilizada para construir el UIKit, por lo que no se almacenan como tales en la información de tiempo de ejecución de ObjC en el binario. es decir, hay un montón de métodos getter/setter, y para los encabezados públicos que acaban de agregar declaraciones de propiedades en lugar de declaraciones de métodos para abreviar. Si realmente fueran propiedades, se mostrarían a través de class_copyPropertyList(), incluso si se declararon en categorías. –

+3

Debe llamar al gratis (propiedades) al final (consulte la documentación). – Sulthan

7

Sí, la función class_copyPropertyList no devolver los bienes definidos en las categorías.

Lo que está sucediendo aquí, es que solo devuelve propiedades definidas en el nivel de clase dado, por lo que solo verá las tres propiedades definidas en UIView y ninguna de las propiedades (normales o de categoría) definidas en el UIResponder y ancestros NSObject.

Para lograr la lista completa heredada; debe recorrer los antepasados ​​a través de la referencia Class.superclass y agregar los resultados de class_copyPropertyList. A continuación, verá, por ejemplo, las diversas propiedades definidas en la categoría Accesibilidad de UIKits para NSObject.

En realidad, vine aquí en busca de una forma de excluir las propiedades definidas en categorías de estos resultados!

+0

¿Terminó encontrando una manera de excluir propiedades de las categorías? – devios1

+0

No, no creo que haya uno.El tiempo de ejecución de Objective-C parece desconocer las categorías una vez que se cargan, lo que probablemente sea algo bueno en el balance. Terminé resolviendo mi problema de otra manera. –

Cuestiones relacionadas