2009-12-11 13 views
6

Actualización Repare el código para eliminar la duplicación de métodos reemplazados y rastrear el autor de la propiedad o el método implementando la sugerencia de Mark. Todavía no he abordado los tipos de propiedad (probablemente comenzaré con property_getAttributes() cuando lo haga). También eliminó los subrayados vestigiales.¿Cómo inspecciono una clase en Objective-C?


Básicamente necesito una manera de recordar a mí mismo qué métodos y propiedades están disponibles en un objeto determinado y sin saltos de todo el camino hasta el árbol de herencia.

he cocinado hasta la siguiente función, pero deja un poco que desear:

#import <objc/runtime.h> 

NSInteger inspectClass_alphabeticSort(id string1, id string2, void *reverse) 
{ 
    if ((NSInteger *)reverse == NO) 
    { 
     return [string2 localizedCaseInsensitiveCompare:string1]; 
    } 
    return [string1 localizedCaseInsensitiveCompare:string2]; 
} 

void inspectClassStopAt(Class inspectedClass, Class stopClass) 
{ 
    Class originalClass    = inspectedClass; 
    NSString *originalClassString = [NSString stringWithFormat:@"%@", originalClass]; 
    NSString *inheritancePath  = [NSString stringWithFormat:@"%@", originalClass]; 

    Method *methods; 
    objc_property_t *properties; 
    unsigned int i; 
    unsigned int methodCount; 
    unsigned int propertyCount; 
    int reverseSort = NO; 

    NSArray *sorted; 
    NSArray *methodsAndPropertiesKeys; 
    NSMutableDictionary * methodsAndProperties = [NSMutableDictionary dictionaryWithCapacity:10]; 

    NSString *inspectedClassString; 
    NSString *methodOrPropertyName; 
    while (inspectedClass != stopClass) 
    { 
     inspectedClassString = [NSString stringWithFormat:@"%@", inspectedClass]; 
     if (inspectedClass != originalClass) 
     { 
      inheritancePath = [inheritancePath stringByAppendingFormat:@" : %@", inspectedClass]; 
     } 

     methods  = class_copyMethodList(inspectedClass, &methodCount); 
     properties = class_copyPropertyList(inspectedClass, &propertyCount); 

     for (i=0; i<methodCount; i++) 
     { 
      methodOrPropertyName = [NSString stringWithFormat:@"-%s", sel_getName(method_getName(methods[i]))]; 

      if (![methodsAndProperties objectForKey:methodOrPropertyName]) 
      { 
       [methodsAndProperties setObject:inspectedClassString forKey:methodOrPropertyName]; 
      } 
     } 

     for (i=0; i<propertyCount; i++) 
     { 
      methodOrPropertyName = [NSString stringWithFormat:@" %s", property_getName(properties[i])]; 

      if (![methodsAndProperties objectForKey:methodOrPropertyName]) 
      { 
       [methodsAndProperties setObject:inspectedClassString forKey:methodOrPropertyName]; 
      } 
     } 

     inspectedClass = [inspectedClass superclass]; 
    } 
    free(methods); 
    free(properties); 

    methodsAndPropertiesKeys = [methodsAndProperties allKeys]; 
    sorted = [methodsAndPropertiesKeys sortedArrayUsingFunction:inspectClass_alphabeticSort context:&reverseSort]; 

    NSLog(@"%@", inheritancePath); 
    for (NSString *key in sorted) 
    { 
     if (![[methodsAndProperties objectForKey:key] isEqualToString:originalClassString]) 
     { 
      NSLog(@"\t%@ (%@)", key, [methodsAndProperties objectForKey:key]); 
     } 
     else 
     { 
      NSLog(@"\t%@", key); 
     } 
    } 
} 

void inspectClass(Class inspectedClass) 
{ 
    inspectClassStopAt(inspectedClass, [NSObject class]); 
} 

Y un ejemplo de salida de inspectClass([TextMap class]);:

TextMap : Surface 
    position (Surface) 
    size (Surface) 
    -addChild: (Surface) 
    -dealloc 
    -init (Surface) 
    -initWithFile: 
    -position (Surface) 
    -render 
    -setPosition: (Surface) 
    -setSize: (Surface) 
    -setText: 
    -size (Surface) 
    -update (Surface) 
+0

¿Cuál es el caso de uso para esto? Pude ver que es útil en la consola del depurador, excepto que allí, puedes completar el código para obtener la misma información. –

+0

Todavía soy relativamente nuevo en Objective-C, así que estoy iterando. Mucho. No para mejorar o refactorizar el código, sino solo para que funcione. Las propiedades y las firmas de métodos cambian mucho de mis expectativas y diseño originales. Sería bueno poder deshacerse de la firma actual de una clase sin tener que pulsar tres o cuatro archivos fuente para armar una imagen clara. La finalización del código no funciona para mí debido a todos los métodos y propiedades no específicos heredados de NSObject. –

+0

¡Parece que la respuesta a esta pregunta está en la pregunta! Buen trabajo. Esto me ayudó mucho. – levous

Respuesta

1

Parece que lo que necesita es un NSMutableDictionary , codificado en los nombres del selector. Agregue el nombre de cada selector al diccionario como una clave, con el nombre de la clase como valor. Puede buscar en el diccionario antes de agregar un selector, para eliminar duplicados.

2

Un ayudante agradable/envoltura para las bibliotecas de C, siempre con runtime.h es https://github.com/mikeash/MAObjCRuntime

Estoy empezando a usar, pero definitivamente parece prometedor.

Por lo que respecta al caso de uso, el mío es simplemente proporcionar un inspector para construir una interfaz de usuario que se pueda conectar a un gráfico de objetos. Eso es una gran reducción de código duplicado potencial.

Cuestiones relacionadas