web-dev-qa-db-fra.com

Qu'est-ce qu'une énumération typedef dans Objective-C?

Je ne pense pas que je comprends fondamentalement ce qu'est une enum et quand l'utiliser.

Par exemple:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Qu'est-ce qui est vraiment déclaré ici?

1080
Craig

Trois choses sont déclarées ici: un type énuméré anonyme est déclaré, ShapeType est déclaré une définition de type pour cette énumération anonyme et les trois noms kCircle, kRectangle et kOblateSpheroid sont déclarés en tant que constantes intégrales.

Décomposons cela. Dans le cas le plus simple, une énumération peut être déclarée comme

enum tagname { ... };

Cela déclare une énumération avec la balise tagname. En C et Objective-C (mais pas C++), toute référence à ce doit être précédée du mot clé enum. Par exemple:

enum tagname x;  // declare x of type 'enum tagname'
tagname x;  // ERROR in C/Objective-C, OK in C++

Afin d'éviter de devoir utiliser le mot clé enum partout, vous pouvez créer un typedef:

enum tagname { ... };
typedef enum tagname tagname;  // declare 'tagname' as a typedef for 'enum tagname'

Ceci peut être simplifié en une seule ligne:

typedef enum tagname { ... } tagname;  // declare both 'enum tagname' and 'tagname'

Enfin, si nous n’avons pas besoin de pouvoir utiliser enum tagname avec le mot clé enum, nous pouvons rendre le enum anonyme et le déclarer uniquement avec le nom de typedef:

typedef enum { ... } tagname;

Maintenant, dans ce cas, nous déclarons que ShapeType est le nom typé d'une énumération anonyme. ShapeType est en réalité simplement un type entier et ne doit être utilisé que pour déclarer des variables contenant l'une des valeurs répertoriées dans la déclaration (c'est-à-dire l'une des kCircle, kRectangle et kOblateSpheroid). Vous pouvez toutefois affecter une autre valeur à la variable ShapeType en la convertissant. Vous devez donc faire attention lorsque vous lisez les valeurs enum.

Enfin, kCircle, kRectangle et kOblateSpheroid sont déclarés en tant que constantes intégrales dans l'espace de noms global. Etant donné qu'aucune valeur spécifique n'a été spécifiée, ils sont affectés à des entiers consécutifs commençant par 0. kCircle vaut donc 0, kRectangle vaut 1 et kOblateSpheroid vaut 2.

1559
Adam Rosenfield

Apple recommande de définir de tels énumérations depuis Xcode 4.4:

typedef enum ShapeType : NSUInteger {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Ils fournissent également une macro pratique NS_ENUM:

typedef NS_ENUM(NSUInteger, ShapeType) {
    kCircle,
    kRectangle,
    kOblateSpheroid
};

Ces définitions permettent une vérification de type plus forte et une meilleure complétion du code. Je ne pouvais pas trouver de documentation officielle de NS_ENUM, mais vous pouvez regarder la vidéo "Modern Objective-C" de la session 2012 de la WWDC ici .

UPDATE: Lien vers la documentation officielle ici .

251

Une énumération déclare un ensemble de valeurs ordonnées - le typedef ajoute simplement un nom pratique à cela. Le 1er élément est 0 etc.

typedef enum {
Monday=1,
...
} WORKDAYS;

WORKDAYS today = Monday;

Ce qui précède n’est qu’une énumération des balises shapeType.

51
hburde

Un type défini par l'utilisateur qui a les valeurs possibles de kCircle, kRectangle ou kOblateSpheroid. Les valeurs à l'intérieur de l'énumération (kCircle, etc.) sont visibles à l'extérieur de l'énumération. Il est important de garder cela à l'esprit (int i = kCircle; est valide, par exemple).

34
Brian Mitchell

Mise à jour pour modification 64 bits: Selon documentation Apple à propos des modifications 64 bits,

Les énumérations sont également typées: dans le compilateur LLVM, les types énumérés peuvent définir la taille de l'énumération. Cela signifie que certains types énumérés peuvent également avoir une taille plus grande que prévue. La solution, comme dans tous les autres cas, consiste à ne pas présumer de la taille d’un type de données. Affectez plutôt les valeurs énumérées à une variable avec le type de données approprié.

Vous devez donc créer une énumération avec la syntaxe type ci-dessous si vous prenez en charge la version 64 bits.

typedef NS_ENUM(NSUInteger, ShapeType) {
    kCircle,
    kRectangle,
    kOblateSpheroid
};

ou

typedef enum ShapeType : NSUInteger {
   kCircle,
   kRectangle,
   kOblateSpheroid
} ShapeType;

Sinon, cela entraînera un avertissement comme Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType

Mise à jour pour la programmation rapide:

Dans Swift, il y a un changement de syntaxe.

enum ControlButtonID: NSUInteger {
        case kCircle , kRectangle, kOblateSpheroid
    }
30
Mani

L'énumération (abréviation d'énumération) est utilisée pour énumérer un ensemble de valeurs (énumérateurs). Une valeur est une chose abstraite représentée par un symbole (un mot). Par exemple, une énumération de base pourrait être

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };

Cette énumération est appelée anonyme car vous n'avez pas de symbole pour la nommer. Mais c'est toujours parfaitement correct. Juste l'utiliser comme ça

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;

D'accord. La vie est belle et tout se passe bien. Mais un jour, vous devez réutiliser cette énumération pour définir une nouvelle variable afin de stocker myGrandFatherPantSize, puis écrivez:

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;

Mais alors vous avez une erreur de compilation "redéfinition de l'énumérateur". En fait, le problème est que le compilateur n'est pas sûr que vous enumiez d'abord et que vous décrivez ensuite la même chose.

Ensuite, si vous souhaitez réutiliser le même ensemble d'énumérateurs (ici xs ... xxxxl) à plusieurs endroits, vous devez lui attribuer un nom unique. La deuxième fois que vous utilisez cet ensemble, il vous suffit d'utiliser la balise. Mais n'oubliez pas que cette balise ne remplace pas le mot enum, mais seulement l'ensemble des énumérateurs. Ensuite, prenez soin d'utiliser enum comme d'habitude. Comme ça:

// Here the first use of my enum
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize; 
// here the second use of my enum. It works now!
enum sizes myGrandFatherPantSize;

vous pouvez également l'utiliser dans une définition de paramètre:

// Observe that here, I still use the enum
- (void) buyANewDressToMyGrandMother:(enum sizes)theSize;

Vous pourriez dire que réécrire enum partout n'est pas pratique et donne un aspect un peu étrange au code. Tu as raison. Un vrai type serait mieux.

C’est la dernière étape de notre grande progression vers le sommet. En ajoutant simplement un typedef transformons notre enum en un type réel. Oh la dernière chose, typedef n'est pas autorisé dans votre classe. Ensuite, définissez votre type juste au-dessus. Fais-le comme ça:

// enum definition
enum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl };
typedef enum sizes size_type

@interface myClass {
   ...
   size_type myGrandMotherDressSize, myGrandFatherPantSize;
   ...
}

Rappelez-vous que la balise est facultative. Ensuite, puisque ici, dans ce cas, nous ne taguons pas les énumérateurs mais simplement pour définir un nouveau type. Ensuite, nous n'en avons plus vraiment besoin.

// enum definition
typedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type;

@interface myClass : NSObject {
  ...
  size_type myGrandMotherDressSize, myGrandFatherPantSize;
  ...
}
@end

Si vous développez en Objective-C avec XCode, je vous laisse découvrir des macros de Nice préfixées par NS_ENUM. Cela devrait vous aider à définir facilement les bonnes énumérations et, en outre, aidera l'analyseur statique à effectuer des vérifications intéressantes pour vous avant de compiler.

Bon Enum!

24
Vincent Zgueb

typedef est utile pour redéfinir le nom d'un type de variable existant. Il fournit un moyen court et significatif d’appeler un type de données. par exemple:

typedef unsigned long int TWOWORDS;

ici, le type unsigned long int est redéfini pour être du type TWOWORDS. Ainsi, nous pouvons maintenant déclarer des variables de type unsigned long int en écrivant,

TWOWORDS var1, var2;

au lieu de

unsigned long int var1, var2;
10
Rajneesh071
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;

alors vous pouvez l'utiliser comme: -

 ShapeType shape;

et

 enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} 
ShapeType;

maintenant vous pouvez l'utiliser comme: -

enum ShapeType shape;
7
Vivek Sehrawat

enum est utilisé pour assigner une valeur aux éléments enum, ce qui ne peut pas être fait dans la structure. Donc à chaque fois, au lieu d’accéder à la variable complète, nous pouvons le faire par la valeur que nous attribuons aux variables enum. Par défaut, il commence par 0 assignation mais nous pouvons lui attribuer n'importe quelle valeur et la variable suivante en enum se verra attribuer une valeur égale à la valeur précédente +1.

3
Priyanka Naik

Une typedef permet au programmeur de définir un type d'Objective-C comme un autre. Par exemple,

typedef int Counter; définit le type Counter comme équivalent au type int. Cela améliore considérablement la lisibilité du code.

2
user4398701

Le Typedef est un mot-clé en C et C++. Il est utilisé pour créer de nouveaux noms pour les types de données de base (char, int, float, double, struct & enum).

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Ici, il crée un type de données énuméré ShapeType & nous pouvons écrire de nouveaux noms pour le type enum ShapeType comme indiqué ci-dessous

ShapeType shape1; 
ShapeType shape2; 
ShapeType shape3;
2
Yogeesh H T

Vous pouvez utiliser dans le format ci-dessous, valeur par défaut brute à partir de 0, afin

  • kCircle est 0,
  • kRectangle est 1,
  • kOblateSpheroid est égal à 2.

Vous pouvez affecter votre propre valeur de départ spécifique.

typedef enum : NSUInteger {
    kCircle, // for your value; kCircle = 5, ...
    kRectangle,
    kOblateSpheroid
} ShapeType;

ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
2
Bilal Arslan

enum peut réduire de nombreux types "d'erreurs" et rendre le code plus maniable

#define STATE_GOOD 0
#define STATE_BAD 1
#define STATE_OTHER 2
int STATE = STATE_OTHER

La définition n'a pas de contraintes. C'est simplement une substitution. Il n'est pas capable de limiter toutes les conditions de l'état. Lorsque le paramètre STATE est attribué à 5, le programme sera erroné car il n'y a pas d'état correspondant. Mais le compilateur ne va pas avertir STATE = 5

Il vaut donc mieux utiliser comme ça

typedef enum SampleState {
    SampleStateGood  = 0,
    SampleStateBad,
    SampleStateOther
} SampleState;

SampleState state = SampleStateGood;
0
Marcus Thornton