web-dev-qa-db-fra.com

Énumération des formes de définition dans Objective-C

Quelle est la différence entre

typedef enum {
    ...
} Name;

et

enum {
    ...
};
typedef NSUInteger Name;

? Si la fonctionnalité est la même, à quoi sert la deuxième forme? N'est-ce pas inutilement salissant?

36
user500

enum est aussi ancien que C, donc une partie de Objective-C. Il s'agit simplement d'un codage explicite d'un type int. C'est très utile pour le débogage et la plupart des compilateurs plus récents peuvent faire des optimisations en fonction de cela. (Ce que vous devez totalement ignorer). Il est très utile pour rendre votre code plus lisible (pour quiconque ou pour vous-même après avoir dormi).

typedef enum {
    ...
} NameType ;

serait suivi par

NameType name;

et c'est généralement le style préféré d'un typedef,

votre deuxième exemple sera pas lier le typedef aux valeurs que vous souhaitez spécifier ne doit être que du type donné.

Notez que cela ne vous empêche pas d'exécuter

name = 10244; // some non-valid value not listed in the enumeration

mais certains compilateurs peuvent générer un avertissement dans ce cas,


Je suis tombé sur l'utilisation par Apple des éléments suivants aujourd'hui:

enum {
NSFetchedResultsChangeInsert = 1,
NSFetchedResultsChangeDelete = 2,
NSFetchedResultsChangeMove = 3,
NSFetchedResultsChangeUpdate = 4
};
typedef NSUInteger NSFetchedResultsChangeType;

Ils le font parce qu'ils veulent vraiment que le NSFetchedResultsChangeType soit du type qu'ils ont défini comme NSUInteger. Ce peut être un int mais il peut aussi être autre chose. Et avec des valeurs de 1, 2, 3 et 4, il est quelque peu hors de propos de s quel est le type. Mais ils codent à un niveau d'abstraction différent car ils sont un fournisseur d'outils.

Vous ne devriez jamais chercher à Apple pour des conseils de style de codage. Si vous voyez quelque chose qui ressemble à une façon plus propre/meilleure de coder, c'est généralement le cas. Comme Kevin l'a mentionné, La stabilité de l'API est d'une importance capitale pour eux.


Edit (Jan 2013) Si vous avez accès aux vidéos de la session WWDC 2012, vous devriez regarder Session 405 - Modern Objective-C 6: 00-10: 00. Il y a une discussion sur une nouvelle syntaxe dans le nouveau compilateur qui permet un dimensionnement explicite d'un type et une liaison étroite des valeurs aux types. (emprunté à C++ 11)

enum NSFetchedResultsChangeType : NSUInteger {
NSFetchedResultsChangeInsert = 1,
NSFetchedResultsChangeDelete = 2,
NSFetchedResultsChangeMove = 3,
NSFetchedResultsChangeUpdate = 4
};
84
bshirley

Le premier définit un nom de type pour faire référence à une énumération. C'est ainsi que la plupart des énumérations sont nommées en C. Ce dernier est cependant un peu différent, et il est répandu dans les frameworks Cocoa. Il y a deux raisons d'utiliser ce dernier. La première est que si votre énumération définit un champ de bits, et que vous le souhaitez ici, car lorsque vous fournissez une valeur "Nom", vous fournirez une combinaison des valeurs énumérées. En d'autres termes, si vous dites quelque chose comme

[self doSomethingWithBitfield:(Enum1 | Enum2)]

vous ne passez pas une valeur de Nom, mais plutôt un entier qui est une combinaison des deux.

Cependant, les frameworks Cocoa utilisent cet idiome même pour des valeurs sans champ de bits, pour une très bonne raison: la stabilité de l'API. Selon la norme C, le type intégral sous-jacent d'une énumération nécessite de pouvoir contenir toutes les valeurs dans l'énumération, mais est autrement choisi par le compilateur. Cela signifie que l'ajout d'une nouvelle valeur d'énumération pourrait changer le type intégral de l'énumération (par exemple, l'ajout de -1 peut le faire signer, l'ajout de 6 milliards peut le transformer en un long long, etc.). C'est une mauvaise chose du point de vue de la stabilité de l'API, car le codage de type des méthodes qui prennent des valeurs de cette énumération pourrait changer de façon inattendue et potentiellement casser le code et les binaires existants. Afin d'éviter cela, les frameworks Cocoa définissent généralement le type comme étant un NSUInteger (ou NSInteger s'ils ont besoin de nombres négatifs), donc l'API et les encodages de type restent stables.

9
Lily Ballard