Obtenir une liste de propriétés d’object dans Objective-C

Comment puis-je obtenir une liste (sous la forme d’un NSArray ou d’un NSDictionary ) d’un object donné dans Objective-C?

Imaginez le scénario suivant: J’ai défini une classe parente qui étend simplement NSObject , qui contient un object NSSsortingng , un object BOOL et un object NSData tant qu’atsortingbuts. Ensuite, j’ai plusieurs classes qui étendent cette classe parente, en ajoutant de nombreux atsortingbuts différents.

Y a-t-il un moyen d’implémenter une méthode d’instance sur la classe parent qui parcourt l’object entier et renvoie, par exemple, un NSArray de chacun des atsortingbuts de classe (enfant) en tant que NSSsortingngs qui ne figurent pas dans la classe parente? utilisez ces NSSsortingng pour KVC?

J’ai juste réussi à obtenir la réponse moi-même. En utilisant la bibliothèque Obj-C Runtime, j’avais access aux propriétés comme je le souhaitais:

 - (void)myMethod { unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList([self class], &outCount); for(i = 0; i < outCount; i++) { objc_property_t property = properties[i]; const char *propName = property_getName(property); if(propName) { const char *propType = getPropertyType(property); NSString *propertyName = [NSString stringWithCString:propName encoding:[NSString defaultCStringEncoding]]; NSString *propertyType = [NSString stringWithCString:propType encoding:[NSString defaultCStringEncoding]]; ... } } free(properties); } 

Cela m'a obligé à créer une fonction C 'getPropertyType', qui est principalement extraite d'un exemple de code Apple (je ne me souviens pas maintenant de la source exacte):

 static const char *getPropertyType(objc_property_t property) { const char *atsortingbutes = property_getAtsortingbutes(property); char buffer[1 + strlen(atsortingbutes)]; strcpy(buffer, atsortingbutes); char *state = buffer, *atsortingbute; while ((atsortingbute = strsep(&state, ",")) != NULL) { if (atsortingbute[0] == 'T') { if (strlen(atsortingbute) <= 4) { break; } return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes]; } } return "@"; } 

La réponse de @boliva est bonne, mais nécessite un petit plus pour gérer les primitives, telles que int, long, float, double, etc.

Je l’ai construit pour append cette fonctionnalité.

 // PropertyUtil.h #import @interface PropertyUtil : NSObject + (NSDictionary *)classPropsFor:(Class)klass; @end // PropertyUtil.m #import "PropertyUtil.h" #import "objc/runtime.h" @implementation PropertyUtil static const char * getPropertyType(objc_property_t property) { const char *atsortingbutes = property_getAtsortingbutes(property); printf("atsortingbutes=%s\n", atsortingbutes); char buffer[1 + strlen(atsortingbutes)]; strcpy(buffer, atsortingbutes); char *state = buffer, *atsortingbute; while ((atsortingbute = strsep(&state, ",")) != NULL) { if (atsortingbute[0] == 'T' && atsortingbute[1] != '@') { // it's a C primitive type: /* if you want a list of what will be returned for these primitives, search online for "objective-c" "Property Atsortingbute Description Examples" apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc. */ return (const char *)[[NSData dataWithBytes:(atsortingbute + 1) length:strlen(atsortingbute) - 1] bytes]; } else if (atsortingbute[0] == 'T' && atsortingbute[1] == '@' && strlen(atsortingbute) == 2) { // it's an ObjC id type: return "id"; } else if (atsortingbute[0] == 'T' && atsortingbute[1] == '@') { // it's another ObjC object type: return (const char *)[[NSData dataWithBytes:(atsortingbute + 3) length:strlen(atsortingbute) - 4] bytes]; } } return ""; } + (NSDictionary *)classPropsFor:(Class)klass { if (klass == NULL) { return nil; } NSMutableDictionary *results = [[[NSMutableDictionary alloc] init] autorelease]; unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList(klass, &outCount); for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; const char *propName = property_getName(property); if(propName) { const char *propType = getPropertyType(property); NSString *propertyName = [NSString stringWithUTF8String:propName]; NSString *propertyType = [NSString stringWithUTF8String:propType]; [results setObject:propertyType forKey:propertyName]; } } free(properties); // returning a copy here to make sure the dictionary is immutable return [NSDictionary dictionaryWithDictionary:results]; } @end 

La réponse de @ orange80 a un problème: elle ne termine pas toujours la chaîne avec des 0. Cela peut conduire à des résultats inattendus, comme un plantage en essayant de le convertir en UTF8 (j’ai en fait eu un crashbug assez ennuyant à cause de ça. C’était amusant de le déboguer ^^). Je l’ai corrigé en obtenant un NSSsortingng de l’atsortingbut et en appelant ensuite cSsortingngUsingEncoding :. Cela fonctionne comme un charme maintenant. (Travaille aussi avec ARC, du moins pour moi)

Voici donc ma version du code:

 // PropertyUtil.h #import @interface PropertyUtil : NSObject + (NSDictionary *)classPropsFor:(Class)klass; @end // PropertyUtil.m #import "PropertyUtil.h" #import  @implementation PropertyUtil static const char *getPropertyType(objc_property_t property) { const char *atsortingbutes = property_getAtsortingbutes(property); //printf("atsortingbutes=%s\n", atsortingbutes); char buffer[1 + strlen(atsortingbutes)]; strcpy(buffer, atsortingbutes); char *state = buffer, *atsortingbute; while ((atsortingbute = strsep(&state, ",")) != NULL) { if (atsortingbute[0] == 'T' && atsortingbute[1] != '@') { // it's a C primitive type: /* if you want a list of what will be returned for these primitives, search online for "objective-c" "Property Atsortingbute Description Examples" apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc. */ NSSsortingng *name = [[NSSsortingng alloc] initWithBytes:atsortingbute + 1 length:strlen(atsortingbute) - 1 encoding:NSASCIISsortingngEncoding]; return (const char *)[name cSsortingngUsingEncoding:NSASCIISsortingngEncoding]; } else if (atsortingbute[0] == 'T' && atsortingbute[1] == '@' && strlen(atsortingbute) == 2) { // it's an ObjC id type: return "id"; } else if (atsortingbute[0] == 'T' && atsortingbute[1] == '@') { // it's another ObjC object type: NSSsortingng *name = [[NSSsortingng alloc] initWithBytes:atsortingbute + 3 length:strlen(atsortingbute) - 4 encoding:NSASCIISsortingngEncoding]; return (const char *)[name cSsortingngUsingEncoding:NSASCIISsortingngEncoding]; } } return ""; } + (NSDictionary *)classPropsFor:(Class)klass { if (klass == NULL) { return nil; } NSMutableDictionary *results = [[NSMutableDictionary alloc] init]; unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList(klass, &outCount); for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; const char *propName = property_getName(property); if(propName) { const char *propType = getPropertyType(property); NSString *propertyName = [NSString stringWithUTF8String:propName]; NSString *propertyType = [NSString stringWithUTF8String:propType]; [results setObject:propertyType forKey:propertyName]; } } free(properties); // returning a copy here to make sure the dictionary is immutable return [NSDictionary dictionaryWithDictionary:results]; } @end 

Lorsque j’ai essayé avec iOS 3.2, la fonction getPropertyType ne fonctionne pas bien avec la description de la propriété. J’ai trouvé un exemple provenant de la documentation iOS: “Guide de programmation Objective-C Runtime: Propriétés déclarées”.

Voici un code révisé pour la liste des biens dans iOS 3.2:

 #import  #import  ... unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList([UITouch 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)); } free(properties); 

J’ai trouvé que la solution de boliva fonctionne bien dans le simulateur, mais sur le périphérique, la sous-chaîne de longueur fixe pose des problèmes. J’ai écrit une solution plus Objective-C-friendly à ce problème qui fonctionne sur l’appareil. Dans ma version, je convertis la chaîne C-Ssortingng des atsortingbuts en NSSsortingng et j’effectue des opérations de chaîne pour obtenir une sous-chaîne de la seule description de type.

 /* * @returns A ssortingng describing the type of the property */ + (NSSsortingng *)propertyTypeSsortingngOfProperty:(objc_property_t) property { const char *attr = property_getAtsortingbutes(property); NSSsortingng *const atsortingbutes = [NSSsortingng ssortingngWithCSsortingng:attr encoding:NSUTF8SsortingngEncoding]; NSRange const typeRangeStart = [atsortingbutes rangeOfSsortingng:@"T@\""]; // start of type ssortingng if (typeRangeStart.location != NSNotFound) { NSSsortingng *const typeSsortingngWithQuote = [atsortingbutes subssortingngFromIndex:typeRangeStart.location + typeRangeStart.length]; NSRange const typeRangeEnd = [typeSsortingngWithQuote rangeOfSsortingng:@"\""]; // end of type ssortingng if (typeRangeEnd.location != NSNotFound) { NSSsortingng *const typeSsortingng = [typeSsortingngWithQuote subssortingngToIndex:typeRangeEnd.location]; return typeSsortingng; } } return nil; } /** * @returns (NSSsortingng) Dictionary of property name --> type */ + (NSDictionary *)propertyTypeDictionaryOfClass:(Class)klass { NSMutableDictionary *propertyMap = [NSMutableDictionary dictionary]; unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList(klass, &outCount); for(i = 0; i < outCount; i++) { objc_property_t property = properties[i]; const char *propName = property_getName(property); if(propName) { NSString *propertyName = [NSString stringWithCString:propName encoding:NSUTF8StringEncoding]; NSString *propertyType = [self propertyTypeStringOfProperty:property]; [propertyMap setValue:propertyType forKey:propertyName]; } } free(properties); return propertyMap; } 

Cette implémentation fonctionne à la fois avec les types d’object Objective-C et les primitives C. Il est compatible avec iOS 8. Cette classe fournit trois méthodes de classe:

 + (NSDictionary *) propertiesOfObject:(id)object; 

Renvoie un dictionnaire de toutes les propriétés visibles d’un object, y compris celles de toutes ses super-classes.

 + (NSDictionary *) propertiesOfClass:(Class)class; 

Retourne un dictionnaire de toutes les propriétés visibles d’une classe, y compris celles de toutes ses super-classes.

 + (NSDictionary *) propertiesOfSubclass:(Class)class; 

Retourne un dictionnaire de toutes les propriétés visibles spécifiques à une sous-classe. Les propriétés de ses superclasses ne sont pas incluses.

Un exemple utile d’utilisation de ces méthodes consiste à copier un object dans une instance de sous-classe dans Objective-C sans avoir à spécifier les propriétés dans une méthode de copie . Certaines parties de cette réponse sont basées sur les autres réponses à cette question, mais fournissent une interface plus propre à la fonctionnalité souhaitée.

Entête:

 // SYNUtilities.h #import  @interface SYNUtilities : NSObject + (NSDictionary *) propertiesOfObject:(id)object; + (NSDictionary *) propertiesOfClass:(Class)class; + (NSDictionary *) propertiesOfSubclass:(Class)class; @end 

La mise en oeuvre:

 // SYNUtilities.m #import "SYNUtilities.h" #import  @implementation SYNUtilities + (NSDictionary *) propertiesOfObject:(id)object { Class class = [object class]; return [self propertiesOfClass:class]; } + (NSDictionary *) propertiesOfClass:(Class)class { NSMutableDictionary * properties = [NSMutableDictionary dictionary]; [self propertiesForHierarchyOfClass:class onDictionary:properties]; return [NSDictionary dictionaryWithDictionary:properties]; } + (NSDictionary *) propertiesOfSubclass:(Class)class { if (class == NULL) { return nil; } NSMutableDictionary *properties = [NSMutableDictionary dictionary]; return [self propertiesForSubclass:class onDictionary:properties]; } + (NSMutableDictionary *)propertiesForHierarchyOfClass:(Class)class onDictionary:(NSMutableDictionary *)properties { if (class == NULL) { return nil; } if (class == [NSObject class]) { // On reaching the NSObject base class, return all properties collected. return properties; } // Collect properties from the current class. [self propertiesForSubclass:class onDictionary:properties]; // Collect properties from the superclass. return [self propertiesForHierarchyOfClass:[class superclass] onDictionary:properties]; } + (NSMutableDictionary *) propertiesForSubclass:(Class)class onDictionary:(NSMutableDictionary *)properties { unsigned int outCount, i; objc_property_t *objcProperties = class_copyPropertyList(class, &outCount); for (i = 0; i < outCount; i++) { objc_property_t property = objcProperties[i]; const char *propName = property_getName(property); if(propName) { const char *propType = getPropertyType(property); NSString *propertyName = [NSString stringWithUTF8String:propName]; NSString *propertyType = [NSString stringWithUTF8String:propType]; [properties setObject:propertyType forKey:propertyName]; } } free(objcProperties); return properties; } static const char *getPropertyType(objc_property_t property) { const char *attributes = property_getAttributes(property); char buffer[1 + strlen(attributes)]; strcpy(buffer, attributes); char *state = buffer, *attribute; while ((attribute = strsep(&state, ",")) != NULL) { if (attribute[0] == 'T' && attribute[1] != '@') { // AC primitive type: /* For example, int "i", long "l", unsigned "I", struct. Apple docs list plenty of examples of values returned. For a list of what will be returned for these primitives, search online for "Objective-c" "Property Attribute Description Examples" */ NSString *name = [[NSString alloc] initWithBytes:attribute + 1 length:strlen(attribute) - 1 encoding:NSASCIIStringEncoding]; return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding]; } else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) { // An Objective C id type: return "id"; } else if (attribute[0] == 'T' && attribute[1] == '@') { // Another Objective C id type: NSString *name = [[NSString alloc] initWithBytes:attribute + 3 length:strlen(attribute) - 4 encoding:NSASCIIStringEncoding]; return (const char *)[name cStringUsingEncoding:NSASCIIStringEncoding]; } } return ""; } @end 

Si quelqu’un a besoin de récupérer les propriétés héritées des classes parentes (comme je l’ai fait), voici quelques modifications sur le code ” orange80 ” pour le rendre récursif:

 + (NSDictionary *)classPropsForClassHierarchy:(Class)klass onDictionary:(NSMutableDictionary *)results { if (klass == NULL) { return nil; } //stop if we reach the NSObject class as is the base class if (klass == [NSObject class]) { return [NSDictionary dictionaryWithDictionary:results]; } else{ unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList(klass, &outCount); for (i = 0; i < outCount; i++) { objc_property_t property = properties[i]; const char *propName = property_getName(property); if(propName) { const char *propType = getPropertyType(property); NSString *propertyName = [NSString stringWithUTF8String:propName]; NSString *propertyType = [NSString stringWithUTF8String:propType]; [results setObject:propertyType forKey:propertyName]; } } free(properties); //go for the superclass return [PropertyUtil classPropsForClassHierarchy:[klass superclass] onDictionary:results]; } } 

Le mot “atsortingbuts” est un peu flou. Voulez-vous dire des variables d’instance, des propriétés, des méthodes qui ressemblent à des accesseurs?

La réponse à tous les trois est “oui, mais ce n’est pas très facile”. L’ API d’exécution Objective-C inclut des fonctions pour obtenir la liste ivar, la liste de méthodes ou la liste de propriétés d’une classe (par exemple, class_copyPropertyList() ), puis une fonction correspondante pour obtenir le nom d’un élément dans la liste (par exemple , property_getName() ).

Globalement, il peut être très compliqué de faire les choses correctement, ou du moins beaucoup plus que ce que la plupart des gens voudraient faire pour ce qui représente généralement une caractéristique vraiment sortingviale.

Alternativement, vous pouvez simplement écrire un script Ruby / Python qui lit simplement un fichier d’en-tête et cherche ce que vous considérez comme des “atsortingbuts” pour la classe.

J’ai été en mesure d’obtenir la réponse de @ orange80 pour travailler avec ARC ENABLED …… pour ce que je voulais – au moins… mais pas sans un peu d’essais et d’erreurs. Espérons que cette information supplémentaire peut épargner à quelqu’un le chagrin.

Enregistrez les classes qu’il décrit dans sa réponse = en tant que classe, et dans votre AppDelegate.h (ou autre), mettez #import PropertyUtil.h . Alors dans ton …

 - (void)applicationDidFinishLaunching: (NSNotification *)aNotification { 

méthode (ou autre)

 PropertyUtil *props = [PropertyUtil new]; NSDictionary *propsD = [PropertyUtil classPropsFor: (NSObject*)[gist class]]; NSLog(@"%@, %@", props, propsD); … 

Le secret est de lancer la variable d’instance de votre classe ( dans ce cas, ma classe est Gist , et mon instance de Gist est gist ) que vous voulez interroger … vers NSObject(id) , etc. .. pour diverses raisons étranges et ésotériques. Cela vous donnera une sortie comme ça…

 , { apiURL = NSURL; createdAt = NSDate; files = NSArray; gistDescription = NSSsortingng; gistId = NSSsortingng; gitPullURL = NSURL; gitPushURL = NSURL; htmlURL = NSURL; isFork = c; isPublic = c; numberOfComments = Q; updatedAt = NSDate; userLogin = NSSsortingng; } 

Pour tous les OCD sans vergogne qui se vantent de l’introspection “amazeballs” d’ObjC … Ils ne rendent certainement pas très facile d’effectuer ce simple “look” “soi-même”, “pour ainsi dire”.

Si vous voulez vraiment aller à travers le monde… allez voir… class-dump , qui est une façon stupide de fouiller dans les en-têtes de classe de n’importe quel exécutable, etc… Il fournit un regard sur VERBOSE dans vos classes… que je, personnellement, trouve vraiment utile – dans de nombreuses circonstances. C’est en fait pourquoi j’ai commencé à chercher une solution à la question du PO. Voici quelques parameters d’utilisation.

  -a show instance variable offsets -A show implementation addresses --arch  choose a specific architecture from a universal binary (ppc, ppc64, i386, x86_64) -C  only display classes matching regular expression -f  find ssortingng in method name -I sort classes, categories, and protocols by inheritance (overrides -s) -r recursively expand frameworks and fixed VM shared libraries -s sort classes and categories by name -S sort methods by name 

J’utilisais la fonction boliva fournie, mais apparemment elle ne fonctionnait plus avec iOS 7. Donc maintenant, au lieu de const char statique * getPropertyType (propriété objc_property_t), on peut simplement utiliser ce qui suit:

 - (NSSsortingng*) classOfProperty:(NSSsortingng*)propName{ objc_property_t prop = class_getProperty([self class], [propName UTF8Ssortingng]); if (!prop) { // doesn't exist for object return nil; } const char * propAttr = property_getAtsortingbutes(prop); NSSsortingng *propSsortingng = [NSSsortingng ssortingngWithUTF8Ssortingng:propAttr]; NSArray *attrArray = [propSsortingng componentsSeparatedBySsortingng:@","]; NSSsortingng *class=[attrArray objectAtIndex:0]; return [[class ssortingngByReplacingOccurrencesOfSsortingng:@"\"" withSsortingng:@""] ssortingngByReplacingOccurrencesOfSsortingng:@"T@" withSsortingng:@""]; } 

Vous avez trois sorts de magie

 Ivar* ivars = class_copyIvarList(clazz, &count); // to get all iVars objc_property_t *properties = class_copyPropertyList(clazz, &count); //to get all properties of a class Method* methods = class_copyMethodList(clazz, &count); // to get all methods of a class. 

Le morceau de code suivant peut vous aider.

 -(void) displayClassInfo { 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* classInfo = [NSDictionary dictionaryWithObjectsAndKeys: ivarArray, @"ivars", propertyArray, @"properties", methodArray, @"methods", nil]; NSLog(@"%@", classInfo); } 

Ces réponses sont utiles, mais j’en ai besoin de plus. Tout ce que je veux faire, c’est vérifier si le type de classe d’une propriété est égal à celui d’un object existant. Tous les codes ci-dessus ne sont pas capables de le faire, car: Pour obtenir le nom de classe d’un object, object_getClassName () renvoie des textes comme ceux-ci:

 __NSArrayI (for an NSArray instance) __NSArrayM (for an NSMutableArray instance) __NSCFBoolean (an NSNumber object initialized by initWithBool:) __NSCFNumber (an NSValue object initialized by [NSNumber initWithBool:]) 

Mais si vous appelez getPropertyType (…) à partir du code ci-dessus, sachez que 4 structures objc_property_t de propriétés d’une classe sont définies comme suit:

 @property (nonatomic, strong) NSArray* a0; @property (nonatomic, strong) NSArray* a1; @property (nonatomic, copy) NSNumber* n0; @property (nonatomic, copy) NSValue* n1; 

il retourne les chaînes respectivement comme suit:

 NSArray NSArray NSNumber NSValue 

Il n’est donc pas en mesure de déterminer si un NSObject peut être la valeur d’une propriété de la classe. Comment faire ça alors?

Voici mon exemple de code complet (la fonction getPropertyType (…) est la même que ci-dessus):

 #import  @interface FOO : NSObject @property (nonatomic, strong) NSArray* a0; @property (nonatomic, strong) NSArray* a1; @property (nonatomic, copy) NSNumber* n0; @property (nonatomic, copy) NSValue* n1; @end @implementation FOO @synthesize a0; @synthesize a1; @synthesize n0; @synthesize n1; @end static const char *getPropertyType(objc_property_t property) { const char *atsortingbutes = property_getAtsortingbutes(property); //printf("atsortingbutes=%s\n", atsortingbutes); char buffer[1 + strlen(atsortingbutes)]; strcpy(buffer, atsortingbutes); char *state = buffer, *atsortingbute; while ((atsortingbute = strsep(&state, ",")) != NULL) { if (atsortingbute[0] == 'T' && atsortingbute[1] != '@') { // it's a C primitive type: // if you want a list of what will be returned for these primitives, search online for // "objective-c" "Property Atsortingbute Description Examples" // apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc. NSSsortingng *name = [[NSSsortingng alloc] initWithBytes:atsortingbute + 1 length:strlen(atsortingbute) - 1 encoding:NSASCIISsortingngEncoding]; return (const char *)[name cSsortingngUsingEncoding:NSASCIISsortingngEncoding]; } else if (atsortingbute[0] == 'T' && atsortingbute[1] == '@' && strlen(atsortingbute) == 2) { // it's an ObjC id type: return "id"; } else if (atsortingbute[0] == 'T' && atsortingbute[1] == '@') { // it's another ObjC object type: NSSsortingng *name = [[NSSsortingng alloc] initWithBytes:atsortingbute + 3 length:strlen(atsortingbute) - 4 encoding:NSASCIISsortingngEncoding]; return (const char *)[name cSsortingngUsingEncoding:NSASCIISsortingngEncoding]; } } return ""; } int main(int argc, char * argv[]) { NSArray* a0 = [[NSArray alloc] init]; NSMutableArray* a1 = [[NSMutableArray alloc] init]; NSNumber* n0 = [[NSNumber alloc] initWithBool:YES]; NSValue* n1 = [[NSNumber alloc] initWithBool:NO]; const char* type0 = object_getClassName(a0); const char* type1 = object_getClassName(a1); const char* type2 = object_getClassName(n0); const char* type3 = object_getClassName(n1); objc_property_t property0 = class_getProperty(FOO.class, "a0"); objc_property_t property1 = class_getProperty(FOO.class, "a1"); objc_property_t property2 = class_getProperty(FOO.class, "n0"); objc_property_t property3 = class_getProperty(FOO.class, "n1"); const char * memberthype0 = getPropertyType(property0);//property_getAtsortingbutes(property0); const char * memberthype1 = getPropertyType(property1);//property_getAtsortingbutes(property1); const char * memberthype2 = getPropertyType(property2);//property_getAtsortingbutes(property0); const char * memberthype3 = getPropertyType(property3);//property_getAtsortingbutes(property1); NSLog(@"%s", type0); NSLog(@"%s", type1); NSLog(@"%s", type2); NSLog(@"%s", type3); NSLog(@"%s", memberthype0); NSLog(@"%s", memberthype1); NSLog(@"%s", memberthype2); NSLog(@"%s", memberthype3); return 0; } 

Pour les spectateurs de Swift, vous pouvez obtenir cette fonctionnalité en utilisant la fonctionnalité Encodable . Je vais expliquer comment:

  1. Conformez votre object au protocole Encodable

     class ExampleObj: NSObject, Encodable { var prop1: Ssortingng = "" var prop2: Ssortingng = "" } 
  2. Créer une extension pour Encodable pour fournir la fonctionnalité toDictionary

      public func toDictionary() -> [Ssortingng: AnyObject]? { let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted guard let data = try? encoder.encode(self), let json = try? JSONSerialization.jsonObject(with: data, options: .init(rawValue: 0)), let jsonDict = json as? [Ssortingng: AnyObject] else { return nil } return jsonDict } 
  3. Appelez toDictionary sur votre instance d’object et propriété de keys access.

     let exampleObj = ExampleObj() exampleObj.toDictionary()?.keys 
  4. Voila! Accédez à vos propriétés comme suit:

     for k in exampleObj!.keys { print(k) } // Prints "prop1" // Prints "prop2"