Comment puis-je obtenir une liste (sous la forme d'un NSArray
ou NSDictionary
) des propriétés d'un objet donné dans Objective-C?
Imaginez le scénario suivant: j'ai défini une classe parente qui ne fait qu'étendre NSObject
, qui contient un NSString
, un BOOL
et un NSData
objet comme propriétés. Ensuite, j'ai plusieurs classes qui étendent cette classe parente, en ajoutant chacune de nombreuses propriétés différentes.
Y a-t-il un moyen pour que je puisse implémenter une méthode d'instance sur la classe parent qui traverse l'objet entier et retourne, disons, une NSArray
de chacune des propriétés de la classe (enfant) car NSStrings
qui ne sont pas sur la classe parent, afin que je puisse les utiliser plus tard NSString
pour KVC?
[NSString stringWithCString:]
est déconseillé en faveur de[NSString stringWithCString:encoding:]
.La réponse de @ boliva est bonne, mais nécessite un petit supplément pour gérer les primitives, comme int, long, float, double, etc.
J'ai construit sur lui pour ajouter cette fonctionnalité.
la source
#import <Foundation/Foundation.h>
en haut du fichier .h?La réponse de @ orange80 a un problème: elle ne termine pas toujours la chaîne par des 0. Cela peut conduire à des résultats inattendus comme un crash en essayant de le convertir en UTF8 (en fait j'ai eu un crashbug assez ennuyeux juste à cause de ça. C'était amusant de le déboguer ^^). Je l'ai corrigé en obtenant un NSString à partir de l'attribut, puis en appelant cStringUsingEncoding :. Cela fonctionne comme un charme maintenant. (Fonctionne également avec ARC, du moins pour moi)
Voici donc ma version du code maintenant:
la source
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 de la documentation iOS: "Objective-C Runtime Programming Guide: Declared Properties".
Voici un code révisé pour la liste des propriétés dans iOS 3.2:
la source
J'ai trouvé que la solution de boliva fonctionne bien dans le simulateur, mais sur l'appareil, la sous-chaîne de longueur fixe pose des problèmes. J'ai écrit une solution plus conviviale pour Objective-C à ce problème qui fonctionne sur l'appareil. Dans ma version, je convertis la chaîne C des attributs en NSString et j'effectue des opérations sur la chaîne pour obtenir une sous-chaîne de la description de type uniquement.
la source
Cette implémentation fonctionne avec les types d'objet Objective-C et les primitives C. Il est compatible iOS 8. Cette classe fournit trois méthodes de classe:
Renvoie un dictionnaire de toutes les propriétés visibles d'un objet, y compris celles de toutes ses superclasses.
Renvoie un dictionnaire de toutes les propriétés visibles d'une classe, y compris celles de toutes ses superclasses.
Renvoie 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 de l'utilisation de ces méthodes est de copier un objet dans une instance de sous-classe en 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 elle fournit une interface plus claire à la fonctionnalité souhaitée.
Entête:
La mise en oeuvre:
la source
Si quelqu'un a besoin d'obtenir également 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:
la source
Le mot «attributs» 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 à ces trois questions est «oui, mais ce n'est pas très facile». L' API d'exécution Objective-C comprend des fonctions pour obtenir la liste ivar, la liste des méthodes ou la liste des propriétés d'une classe (par exemple,
class_copyPropertyList()
), puis une fonction correspondante pour chaque type pour obtenir le nom d'un élément dans la liste (par exemple,property_getName()
).Dans l'ensemble, cela peut demander beaucoup de travail pour bien faire les choses, ou du moins beaucoup plus que ce que la plupart des gens voudraient faire pour ce qui est généralement une fonctionnalité vraiment triviale.
Alternativement, vous pouvez simplement écrire un script Ruby / Python qui lit simplement un fichier d'en-tête et recherche tout ce que vous considérez comme des «attributs» pour la classe.
la source
J'ai pu faire fonctionner la réponse de @ orange80 AVEC ARC ENABLED ... ... pour ce que je voulais - du moins ... mais pas sans un peu d'essais et d'erreurs. Espérons que ces informations supplémentaires peuvent é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
. Puis dans votre ...méthode (ou autre)
…
Le secret est de convertir la variable d'instance de votre classe ( dans ce cas, ma classe est
Gist
, et mon instance deGist
estgist
) que vous voulez interroger ... en NSObject ...(id)
, etc., ne la coupera pas .. pour divers, bizarre , des raisons ésotériques. Cela vous donnera une sortie comme ça ...Pour toutes les vantardises d'Apple / TOC à propos de l'introspection "amazeballs" "d'ObjC ... Ils ne rendent certainement pas très facile d'effectuer ce simple" regard "" sur soi-même "," pour ainsi dire "..
Si vous voulez vraiment devenir sauvage par contre ... consultez .. class-dump , qui est un moyen incroyablement insensé de jeter un coup d'œil dans les en-têtes de classe de TOUT exécutable, etc. Cela fournit un regard VERBOSE sur vos classes ... personnellement, trouvez vraiment utile - dans de très nombreuses circonstances. c'est en fait pourquoi j'ai commencé à chercher une solution à la question du PO. voici quelques paramètres d'utilisation .. profitez-en!
la source
Vous avez trois sorts magiques
Le morceau de code suivant peut vous aider.
la source
J'utilisais la fonction boliva fournie, mais apparemment elle a cessé de fonctionner avec iOS 7. Alors maintenant, au lieu de static const char * getPropertyType (propriété objc_property_t), on peut simplement utiliser ce qui suit:
la source
Pour les spectateurs Swift, vous pouvez obtenir cette fonctionnalité en utilisant la
Encodable
fonctionnalité. Je vais vous expliquer comment:Conformez votre objet au
Encodable
protocoleCréer une extension pour
Encodable
fournir destoDictionary
fonctionnalitésAppelez
toDictionary
votre instance d'objet et accédez à lakeys
propriété.Voila! Accédez à vos propriétés comme ceci:
la source
Ces réponses sont utiles, mais j'en demande davantage. Tout ce que je veux faire, c'est vérifier si le type de classe d'une propriété est égal à celui d'un objet existant. Tous les codes ci-dessus ne sont pas capables de le faire, car: Pour obtenir le nom de classe d'un objet, object_getClassName () renvoie des textes comme ceux-ci:
Mais si vous appelez getPropertyType (...) à partir de l'exemple de code ci-dessus, avec 4 structures objc_property_t de propriétés d'une classe définie comme ceci:
il renvoie les chaînes respectivement comme suit:
Il n'est donc pas en mesure de déterminer si un NSObject est capable d'ê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):
la source