Che cos'è un enumerazione typedef in Objective-C?


1087

Non penso di aver capito fondamentalmente cosa enumsia e quando usarlo.

Per esempio:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Cosa viene realmente dichiarato qui?


2
Il tipo definito dall'utente è chiamato "enum"? Questo è quello che avevo pensato, fino a quando non mi sono imbattuto in codice che aveva più dichiarazioni enumerate tipicamente.
Craig

8
No, il tipo definito dall'utente è ShapeType. Leggi su typedef: en.wikipedia.org/wiki/Typedef
rampion

6
Un typedef in Objective-C è esattamente lo stesso di un typedef in C. E un enum in Objective-C è esattamente lo stesso di un enum in C. Questo dichiara un enum con tre costanti kCircle = 0, kRectangle = 1 e kOblateSpheroid = 2 e dà al tipo enum il nome ShapeType. Se non sai cosa significano "typedef" e "enum", acquista un libro su C.
gnasher729

Risposte:


1565

Tre cose vengono dichiarati qui: un tipo enumerato anonimo è dichiarata, ShapeTypeviene dichiarata una typedef per che l'enumerazione anonima, ed i tre nomi kCircle, kRectanglee kOblateSpheroidvengono dichiarati come costanti integrale.

Analizziamolo. Nel caso più semplice, un'enumerazione può essere dichiarata come

enum tagname { ... };

Questo dichiara un'enumerazione con il tag tagname. In C e Objective-C (ma non in C ++), qualsiasi riferimento a questo deve essere preceduto dalla enumparola chiave. Per esempio:

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

Per evitare di dover usare la enumparola chiave ovunque, è possibile creare un typedef:

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

Questo può essere semplificato in una riga:

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

E infine, se non abbiamo bisogno di essere in grado di utilizzare enum tagnamela enumparola chiave, possiamo rendere l' enumanonimo e dichiararlo solo con il nome typedef:

typedef enum { ... } tagname;

Ora, in questo caso, dichiariamo ShapeTypedi essere un nome dattiloscritto di un elenco anonimo. ShapeTypeè in realtà solo un tipo intero, e deve essere utilizzato solo per dichiarare variabili che contengono uno dei valori riportati nella dichiarazione (cioè, uno kCircle, kRectanglee kOblateSpheroid). ShapeTypeTuttavia, puoi assegnare una variabile a un altro valore eseguendo il cast, quindi devi fare attenzione quando leggi i valori enum.

Infine, kCircle, kRectangle, e kOblateSpheroidsono dichiarati come costanti integrale nel namespace globale. Poiché non sono stati specificati valori specifici, vengono assegnati a numeri interi consecutivi che iniziano con 0, quindi kCircleè 0, kRectangleè 1 e kOblateSpheroidè 2.


6
Bella spiegazione - solo per aggiungere una cosa, le strutture seguono regole di denominazione simili in C (non sono sicuro di Objective-C).
Michael Burr,

109
Objective-C è un superset proprio di C. Tutte le regole di denominazione della struttura C in C sono valide anche in Objective-C.
sigjuice,

Eccezionale. Posso semplicemente usare enum in stile C ++ e anche non ho bisogno di scrivere enum :)
user4951

11
È possibile utilizzare gli enumerazioni in stile C ++ se il file in cui vengono dichiarati è un file .mm anziché un .m. Objective-C ++ è assurdamente potente.
Kevin Hoffman,

14
E una volta che hai la testa intorno a questa risposta, vale la pena guardare i nuovi NS_ENUM e NS_OPTIONS. Tutorial qui: nshipster.com/ns_enum-ns_options e così qui: stackoverflow.com/questions/14080750/...
Snowcrash

254

Apple consiglia di definire enum come questo da Xcode 4.4 :

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

Forniscono anche una pratica macro NS_ENUM:

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

Queste definizioni forniscono un controllo del tipo più forte e un migliore completamento del codice. Non sono riuscito a trovare la documentazione ufficiale di NS_ENUM, ma puoi guardare il video "Modern Objective-C" dalla sessione del WWDC 2012 qui .


AGGIORNAMENTO
Link alla documentazione ufficiale qui .


13
La parte su "Enum Improvements" inizia alle 5:58
vikingosegundo,

5
Come commentato su un'altra risposta, vedi la spiegazione della NS_ENUMmacro di Apple di NSHipster: NSHipster.com/ns_enum-ns_options
Basil Bourque,

1
Questo è il link alla documentazione ufficiale su NS_ENUM: developer.apple.com/library/ios/releasenotes/ObjectiveC/…
YoGiN

50

Un enum dichiara un insieme di valori ordinati - il typedef aggiunge semplicemente un nome utile a questo. Il primo elemento è 0 ecc.

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

WORKDAYS today = Monday;

Quanto sopra è solo un elenco di tag shapeType.


34

Un tipo definito dall'utente che contiene i valori possibili di kCircle, kRectangleo kOblateSpheroid. Tuttavia, i valori all'interno dell'enum (kCircle, ecc.) Sono visibili all'esterno dell'enum. È importante tenerlo presente ( int i = kCircle;è valido, ad esempio).


30

Aggiornamento per la modifica a 64 bit: in base ai documenti di Apple sulle modifiche a 64 bit,

Le enumerazioni vengono anche digitate: nel compilatore LLVM, i tipi enumerati possono definire la dimensione dell'enumerazione. Ciò significa che alcuni tipi enumerati potrebbero anche avere una dimensione maggiore di quanto ci si aspetti. La soluzione, come in tutti gli altri casi, è di non fare ipotesi sulla dimensione di un tipo di dati. Assegnare invece i valori enumerati a una variabile con il tipo di dati appropriato

Quindi devi creare enum con type come sotto sintassi se supporti per 64-bit.

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

o

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

Altrimenti, porterà ad avvertimento come Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType

Aggiornamento per programmazione rapida:

In rapido, c'è un cambio di sintassi.

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

Se necessità di dichiarare avanti enum (NS_ENUM): stackoverflow.com/a/42009056/342794
lal

25

L'enum (abbreviazione di enumerazione) viene utilizzato per enumerare un insieme di valori (enumeratori). Un valore è una cosa astratta rappresentata da un simbolo (una parola). Ad esempio, potrebbe essere un enum di base

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

Questo enum è chiamato anonimo perché non hai un simbolo per nominarlo. Ma è ancora perfettamente corretto. Usalo così

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

Ok. La vita è bella e tutto va bene. Ma un giorno devi riutilizzare questo enum per definire una nuova variabile per memorizzare myGrandFatherPantSize, quindi scrivi:

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

Ma poi hai un errore del compilatore "ridefinizione dell'enumeratore". In realtà, il problema è che il compilatore non è sicuro che tu entri per primo e tu sia il secondo a descrivere la stessa cosa.

Quindi se si desidera riutilizzare lo stesso set di enumeratori (qui xs ... xxxxl) in più punti, è necessario contrassegnarlo con un nome univoco. La seconda volta che usi questo set devi solo usare il tag. Ma non dimenticare che questo tag non sostituisce la parola enum ma solo il set di enumeratori. Quindi abbi cura di usare enum come al solito. Come questo:

// 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;

puoi usarlo anche nella definizione di un parametro:

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

Potresti dire che riscrivere enum ovunque non è conveniente e rende il codice un po 'strano. Hai ragione. Un tipo reale sarebbe migliore.

Questo è l'ultimo passo della nostra grande progressione verso il vertice. Aggiungendo semplicemente un typedef trasformiamo il nostro enum in un tipo reale. Oh, l'ultima cosa, typedef non è consentito all'interno della tua classe. Quindi definisci il tuo tipo appena sopra. Fai cosi:

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

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

Ricorda che il tag è facoltativo. Quindi poiché qui, in quel caso, non etichettiamo gli enumeratori ma solo per definire un nuovo tipo. Quindi non ne abbiamo più bisogno.

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

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

Se stai sviluppando in Objective-C con XCode ti faccio scoprire alcuni bei macro con prefisso NS_ENUM. Ciò dovrebbe aiutarti a definire facilmente i buoni enum e inoltre aiuterà l'analizzatore statico a fare alcuni controlli interessanti prima di compilare.

Buon enum!


Ho sempre pensato "perché qualcuno dovrebbe rispondere a una domanda a cui è già stata data una risposta e accettata". Ragazzo, mi sbagliavo sempre! Questa è la risposta migliore e aiuta i principianti come me!
rak appdev,

10

typedefè utile per ridefinire il nome di un tipo di variabile esistente. Fornisce un modo breve e significativo per chiamare un tipo di dati. per esempio:

typedef unsigned long int TWOWORDS;

qui, il tipo unsigned long int viene ridefinito per essere del tipo TWOWORDS. Pertanto, ora possiamo dichiarare variabili di tipo unsigned long int scrivendo,

TWOWORDS var1, var2;

invece di

unsigned long int var1, var2;

7
typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;

allora puoi usarlo come: -

 ShapeType shape;

e

 enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} 
ShapeType;

ora puoi usarlo come: -

enum ShapeType shape;

3

enum è usato per assegnare valore a enum elementi che non possono essere fatti in struct. Quindi ogni volta invece di accedere alla variabile completa possiamo farlo in base al valore che assegniamo alle variabili in enum. Di default inizia con 0 assegnazione ma possiamo assegnargli qualsiasi valore e alla variabile successiva in enum verrà assegnato un valore il valore precedente +1.


3

È possibile utilizzare nel formato seguente, valore predefinito Raw a partire da 0, quindi

  • kCircle è 0,
  • kRectangle è 1,
  • kOblateSpheroid è 2.

È possibile assegnare il proprio valore iniziale specifico.

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

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

2

Un typedef consente al programmatore di definire un tipo Objective-C come un altro. Per esempio,

typedef int Contatore; definisce il tipo Counter come equivalente al tipo int. Ciò migliora drasticamente la leggibilità del codice.


2

Typedef è una parola chiave in C e C ++. Viene utilizzato per creare nuovi nomi per i tipi di dati di base (char, int, float, double, struct & enum) .

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Qui crea il tipo di dati enumerato ShapeType e possiamo scrivere nuovi nomi per il tipo enum ShapeType come indicato di seguito

ShapeType shape1; 
ShapeType shape2; 
ShapeType shape3;

1

enum può ridurre molti tipi di "errori" e rendere il codice più gestibile

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

La definizione non ha vincoli. È semplicemente solo una sostituzione. Non è in grado di limitare tutte le condizioni dello stato. Quando lo STATO è assegnato a 5, il programma sarà errato, perché non esiste uno stato corrispondente. Ma il compilatore non avviserà STATE = 5

Quindi è meglio usare così

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

SampleState state = SampleStateGood;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.