79 votes

Introspection / réflexion de l'objectif C

Est-il intégré dans la méthode, une fonction de l'API, communément acceptée, etc. vider le contenu d'un objet instancié en Objective-C, plus précisément dans la Pomme de Cacao/Cacao-Touch de l'environnement?

Je veux être en mesure de faire quelque chose comme

MyType *the_thing = [[MyType alloc] init];
NSString *the_dump = [the_thing dump]; //pseudo code
NSLog("Dumped Contents: %@", the_dump);

et ont l'instance de l'objet de noms de variables et les valeurs affichées, avec toutes les méthodes disponibles à l'appel au moment de l'exécution. Idéalement dans un format facile à lire.

Pour les développeurs qui connaissent le PHP, je suis fondamentalement de la recherche de l'équivalent de la réflexion fonctions (var_dump(), get_class_methods()) et de l'OO API Reflection.

112voto

Felixyz Points 10705

Mise à JOUR: ceux qui cherchent à faire ce genre de choses pourrait vouloir vérifier Mike Ash ObjC wrapper pour l'Objective-C runtime.

C'est plus ou moins comment vous pouvez aller à ce sujet:

#import <objc/runtime.h>

. . . 

-(void)dumpInfo
{
    Class clazz = [self class];
    u_int count;

    Ivar* ivars = class_copyIvarList(clazz, &count);
    NSMutableArray* ivarArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count ; i++)
    {
        const char* ivarName = ivar_getName(ivars[i]);
        [ivarArray addObject:[NSString  stringWithCString:ivarName encoding:NSUTF8StringEncoding]];
    }
    free(ivars);

    objc_property_t* properties = class_copyPropertyList(clazz, &count);
    NSMutableArray* propertyArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count ; i++)
    {
        const char* propertyName = property_getName(properties[i]);
        [propertyArray addObject:[NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding]];
    }
    free(properties);

    Method* methods = class_copyMethodList(clazz, &count);
    NSMutableArray* methodArray = [NSMutableArray arrayWithCapacity:count];
    for (int i = 0; i < count ; i++)
    {
        SEL selector = method_getName(methods[i]);
        const char* methodName = sel_getName(selector);
        [methodArray addObject:[NSString  stringWithCString:methodName encoding:NSUTF8StringEncoding]];
    }
    free(methods);

    NSDictionary* classDump = [NSDictionary dictionaryWithObjectsAndKeys:
                               ivarArray, @"ivars",
                               propertyArray, @"properties",
                               methodArray, @"methods",
                               nil];

    NSLog(@"%@", classDump);
}

À partir de là, il est facile d'obtenir les valeurs réelles d'une instance de propriétés, mais vous devez vérifier pour voir si elles sont de type primitif ou d'objets, de sorte que j'ai été trop paresseux pour le mettre. Vous pouvez également choisir d'analyser la chaîne d'héritage pour obtenir toutes les propriétés définies sur un objet. Ensuite, il existe des méthodes définies selon les catégories, et plus... Mais presque tout est facilement disponible.

Voici un extrait de ce que le code ci-dessus dumps pour UILabel:

{
    ivars =     (
        "_size",
        "_text",
        "_color",
        "_highlightedColor",
        "_shadowColor",
        "_font",
        "_shadowOffset",
        "_minFontSize",
        "_actualFontSize",
        "_numberOfLines",
        "_lastLineBaseline",
        "_lineSpacing",
        "_textLabelFlags"
    );
    methods =     (
        rawSize,
        "setRawSize:",
        "drawContentsInRect:",
        "textRectForBounds:",
        "textSizeForWidth:",
        . . .
    );
    properties =     (
        text,
        font,
        textColor,
        shadowColor,
        shadowOffset,
        textAlignment,
        lineBreakMode,
        highlightedTextColor,
        highlighted,
        enabled,
        numberOfLines,
        adjustsFontSizeToFitWidth,
        minimumFontSize,
        baselineAdjustment,
        "_lastLineBaseline",
        lineSpacing,
        userInteractionEnabled
    );
}

12voto

Dave DeLong Points 156978

De la `` méthode (comme .toString() en Java), je n’ai pas entendu parler de celui qui a été construit en, mais il ne serait pas trop difficile d’en créer un. L’Objective-C Runtime Reference a un tas de fonctions, que vous pouvez utiliser pour obtenir des informations sur les variables d’instance de l’objet, méthodes, propriétés, etc..

8voto

Voici ce que j’utilise actuellement pour imprimer automatiquement les variables de classe, dans une bibliothèque pour éventuelle diffusion publique - il fonctionne par le dumping de toutes les propriétés de la classe instance tout le chemin du retour vers le haut de l’arborescence d’héritage. Grâce à KVC vous n’avez pas besoin de soin si une propriété est un type primitif ou pas (pour la plupart).

4voto

J’ai fait quelques modifications au code de Kendall pour des valeurs de propriétés d’impression, qui est entré en très pratique pour moi. J’ai défini comme une méthode d’instance au lieu d’une méthode de classe, car c’est comment l’appelle la récursivité de la superclasse. J’ai également ajouté les gestions d’exceptions pour les propriétés non compatibles KVO et ajouté des sauts de ligne à la sortie pour le rendre plus facile à lire (et diff) :

3voto

Colin Barrett Points 3581

Honnêtement, le bon outil pour ce travail est le débogueur de Xcode. Il a toutes ces informations facilement accessibles de manière visuelle. Prenez le temps d’apprendre comment l’utiliser, c’est un outil vraiment puissant. Plus d’informations : Guide de débogage de Xcode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X