En supposant que j'ai un typedef déclaré dans mon fichier .h comme tel:
typedef enum {
JSON,
XML,
Atom,
RSS
} FormatType;
Je voudrais créer une fonction qui convertit la valeur numérique du typedef en une chaîne. Par exemple, si le message a [self toString:JSON]
été envoyé; il renverrait «JSON».
La fonction ressemblerait à ceci:
-(NSString *) toString:(FormatType)formatType {
//need help here
return [];
}
Incidemment, si j'essaye cette syntaxe
[self toString:FormatType.JSON];
pour passer la valeur typedef à la méthode, j'obtiens une erreur. Qu'est-ce que je rate?
c
objective-c
enums
typedef
Craig
la source
la source
Réponses:
C'est vraiment une question C, non spécifique à Objective-C (qui est un sur-ensemble du langage C). Les énumérations en C sont représentées sous forme d'entiers. Vous devez donc écrire une fonction qui renvoie une chaîne avec une valeur d'énumération. Il existe de nombreuses façons de procéder. Un tableau de chaînes tel que la valeur enum peut être utilisée comme un index dans le tableau ou une structure de carte (par exemple un
NSDictionary
) qui mappe une valeur enum à une chaîne de travail, mais je trouve que ces approches ne sont pas aussi claires qu'une fonction qui rend la conversion explicite (et l'approche tableau, bien que laC
méthode classique soit dangereuse si vos valeurs d'énumération ne sont pas contingentes à partir de 0). Quelque chose comme ça fonctionnerait:Votre question relative à la syntaxe correcte d'une valeur enum est que vous n'utilisez que la valeur (par exemple
JSON
), pas laFormatType.JSON
syntaxe.FormatType
est un type et les valeurs de ENUM (par exempleJSON
,XML
, etc.) sont des valeurs que vous pouvez attribuer à ce type.la source
Vous ne pouvez pas le faire facilement. En C et Objective-C, les énumérations ne sont en réalité que des constantes entières glorifiées. Vous devrez générer vous-même une table de noms (ou avec un abus de préprocesseur). Par exemple:
Le danger de cette approche est que si jamais vous changez l'énumération, vous devez vous rappeler de changer le tableau de noms. Vous pouvez résoudre ce problème avec un abus de préprocesseur, mais c'est délicat et laid.
Notez également que cela suppose que vous disposez d'une constante d'énumération valide. Si vous avez une valeur entière à partir d' une source non fiable, vous devez en plus de faire une vérification que votre constante est valable, par exemple en incluant une valeur « passé max » dans votre ENUM, ou en vérifiant si elle est inférieure à la longueur du tableau,
sizeof(FormatType_toString) / sizeof(FormatType_toString[0])
.la source
string[] = { [XML] = "XML" }
pour vous assurer que la chaîne correspond correctementFormatType_toString[]
tableau et appeler-isEqualToString:
chaque élément pour trouver une correspondance, soit utiliser un type de données de mappage tel queNSDictionary
pour maintenir la carte de recherche inverse.FormatType_toString
tableau.Ma solution:
modifier: j'ai ajouté une solution encore meilleure à la fin, en utilisant Modern Obj-C
1.
Mettez les noms sous forme de clés dans un tableau.
Assurez-vous que les index sont les énumérations appropriées et dans le bon ordre (sinon exception).
note: names est une propriété synthétisée sous forme de * _names *;
le code n'a pas été vérifié pour la compilation, mais j'ai utilisé la même technique dans mon application.
//
2.
En utilisant Modern Obj-C, nous pouvons utiliser un dictionnaire pour lier les descriptions aux clés de l'énumération.
L'ordre n'a pas d'importance .
Utilisation (dans une méthode d'instance de classe):
la source
+[typeDisplayNames]
, vous recréez le dictionnaire. C'est très bien si elle n'est appelée que quelques fois, mais si elle est appelée plusieurs fois, cela coûtera très cher. Une meilleure solution peut être de faire du dictionnaire un singleton, de sorte qu'il ne soit créé qu'une seule fois et reste en mémoire sinon. Mémoire classique contre énigme CPU.static NSDictionary *dict = nil; if(!dict) dict = @{@(UserTypeParent): @"Parent"}; return dict;
commentaires ne vous laisseront pas de saut de ligne, désolé pour cela.En combinant la réponse @AdamRosenfield, le commentaire @Christoph et une autre astuce pour gérer les énumérations C simples, je suggère:
Dans le pire des cas - comme si vous changez l'énumération mais oubliez de changer le tableau des noms - il renverra nil pour cette clé.
la source
définir typedef enum dans l'en-tête de classe:
écrivez une méthode comme celle-ci en classe:
avoir les chaînes dans le fichier Localizable.strings :
la source
J'utiliserais le jeton # string du compilateur (avec des macros pour le rendre plus compact):
la source
J'aime la
#define
façon de procéder:// Placez ceci dans votre fichier .h, en dehors du bloc @interface
source(la source n'est plus disponible)la source
nil
siarray.count <= enumValue
?J'ai fait une sorte de mélange de toutes les solutions trouvées sur cette page pour créer la mienne, c'est une sorte d'extension enum orientée objet ou quelque chose comme ça.
En fait, si vous avez besoin de plus que de simples constantes (c'est-à-dire des entiers), vous avez probablement besoin d'un objet modèle (nous parlons tous de MVC, non?)
Posez-vous simplement la question avant d'utiliser ceci, ai-je raison, n'avez-vous pas en fait besoin d'un objet modèle réel, initialisé à partir d'un webservice, d'un plist, d'une base de données SQLite ou de CoreData?
Quoi qu'il en soit, voici le code (MPI est pour "My Project Initials", tout le monde utilise tel ou tel nom, semble-t-il):
MyWonderfulType.h
:Et
MyWonderfulType.m
:la source
Une autre solution:
Dans votre méthode, vous pouvez utiliser:
la source
Réponse @ yar1vn améliorée en supprimant la dépendance de chaîne:
Ainsi, lorsque vous modifierez le nom de l'entrée d'énumération, la chaîne correspondante sera modifiée. Utile si vous n'allez pas montrer cette chaîne à l'utilisateur.
la source
"foo""bar"
, il en résulte la chaîne"foobar"
lors de la compilation. Donc,#define VariableName(arg) (@""#arg)
va se développerVariableName(MyEnum)
pour être(@"""MyEnum")
. Cela se traduira par la chaîne@"MyEnum"
.Étant donné une définition enum comme:
Nous pouvons définir une macro pour convertir une valeur enum en sa chaîne correspondante, comme indiqué ci-dessous.
L'
switch
instruction utilisée dans le bloc est pour la vérification de type, ainsi que pour obtenir la prise en charge de la saisie semi-automatique dans Xcode.la source
J'avais un grand type énuméré que je voulais convertir en une
NSDictionary
recherche. J'ai fini par utilisersed
depuis le terminal OSX comme:qui peut être lu comme: 'capturer le premier mot sur la ligne et afficher @ (mot): @ "mot",'
Cette regex convertit l'énumération dans un fichier d'en-tête nommé 'ObservationType.h' qui contient:
en quelque chose comme:
qui peut ensuite être enveloppé dans une méthode utilisant la syntaxe objective-c moderne
@{ }
(comme expliqué par @ yar1vn ci-dessus) pour créer uneNSDictionary
recherche:La
dispatch_once
plaque chauffante sert uniquement à garantir que la variable statique est initialisée de manière thread-safe.Remarque: j'ai trouvé l'expression regex sed sur OSX étrange - lorsque j'ai essayé d'utiliser
+
pour correspondre à `` un ou plusieurs '', cela ne fonctionnait pas et j'ai dû recourir à l'utilisation{1,}
en remplacementla source
J'utilise une variante de la réponse de Barry Walk, qui, par ordre d'importance:
PAR EXEMPLE:
la source
@pixel a ajouté la réponse la plus brillante ici: https://stackoverflow.com/a/24255387/1364257 S'il vous plaît, votez pour lui!
Il utilise la macro X soignée des années 1960. (J'ai un peu changé son code pour l'ObjC moderne)
C'est tout. Propre et soigné. Merci à @pixel! https://stackoverflow.com/users/21804/pixel
la source
J'ai combiné plusieurs approches ici. J'aime l'idée du préprocesseur et la liste indexée.
Il n'y a pas d'allocation dynamique supplémentaire, et en raison de l'inlining, le compilateur pourrait être en mesure d'optimiser la recherche.
la source
Tout d'abord, en ce qui concerne FormatType.JSON: JSON n'est pas membre de FormatType, c'est une valeur possible du type. FormatType n'est même pas un type composite - c'est un scalaire.
Deuxièmement, la seule façon de procéder est de créer une table de mappage. La façon la plus courante de faire cela en Objective-C est de créer une série de constantes faisant référence à vos "symboles", donc vous auriez
NSString *FormatTypeJSON = @"JSON"
, etc.la source
ce qui suit fournit une solution telle que l'ajout d'une nouvelle énumération ne nécessite qu'une modification sur une ligne, un travail similaire à l'ajout d'une seule ligne dans une liste enum {}.
la source
Chaque réponse ici dit essentiellement la même chose, créez une énumération régulière, puis utilisez un getter personnalisé pour basculer entre les chaînes.
J'emploie une solution beaucoup plus simple qui est plus rapide, plus courte et plus propre - en utilisant des macros!
Ensuite, vous pouvez simplement commencer à taper
kNam...
et la saisie semi-automatique affichera les listes que vous désirez!De plus, si vous souhaitez gérer la logique de tous les noms à la fois, vous pouvez simplement énumérer rapidement le tableau littéral dans l'ordre, comme suit:
for (NSString *kName in kNames_allNames) {}
Enfin, le casting NSString dans les macros garantit un comportement similaire à typedef!
Prendre plaisir!
la source
De nombreuses réponses sont toutes assez bonnes.
Si vous recherchez une solution Objective C générique qui utilise certaines macros ...
La caractéristique clé est qu'elle utilise l'énumération comme index dans un tableau statique de constantes NSString. le tableau lui-même est enveloppé dans une fonction pour le faire ressembler davantage à la suite de fonctions NSStringFromXXX répandue dans les API Apple.
vous devrez
#import "NSStringFromEnum.h"
trouver ici http://pastebin.com/u83RR3Vk[EDIT] doit également être
#import "SW+Variadic.h"
trouvé ici http://pastebin.com/UEqTzYLfExemple 1: définissez complètement un NOUVEAU typedef enum, avec des convertisseurs de chaîne.
dans myfile.h
dans myfile.m:
utiliser :
NSStringFromEnumDispatch_chain_cmd(chain_for_c)
Retour@"chain_for_c"
enumDispatch_chain_cmdFromNSString(@"chain_previous")
Retourchain_previous
Exemple 2: fournir des routines de conversion pour une énumération existante montre également l'utilisation d'une chaîne de paramètres et le changement de nom du type utilisé dans les fonctions.
dans myfile.h
dans myfile.m:
la source
Ici fonctionne -> https://github.com/ndpiparava/ObjcEnumString
la source
En fonction de vos besoins, vous pouvez également utiliser les directives du compilateur pour simuler le comportement que vous recherchez.
Rappelez-vous simplement les défauts habituels du compilateur (le type n'est pas sûr, le copier-coller direct agrandit le fichier source)
la source
#define
est visible, vous ne pourrez pas utiliser la valeur d'énumération réelle (c.-àJSON
- d. sera remplacé@"JSON"
par le préprocesseur et entraînera une erreur du compilateur lors de l'assignation à unFormatType
.