objective-c - objective c define enum




Cos'è un typedef enum in Objective-C? (10)

Non penso di capire fondamentalmente cos'è un enum e quando usarlo.

Per esempio:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

Cosa viene realmente dichiarato qui?


È 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

Apple consiglia di definire enumerazioni come questa 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 più accurato del tipo e un migliore completamento del codice. Non sono riuscito a trovare una documentazione ufficiale di NS_ENUM, ma puoi guardare il video "Modern Objective-C" della sessione WWDC 2012 here .

AGGIORNAMENTO: collegamento alla documentazione ufficiale here .


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

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

Questo enum è chiamato anonimo perché non hai un simbolo per nominarlo. Ma è ancora perfettamente corretto. Basta usarlo in questo modo

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

Ok. La vita è bella e tutto va bene. Ma un giorno è necessario 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 di essere il primo enum e il secondo di descrivere la stessa cosa.

Quindi se si desidera riutilizzare lo stesso insieme di enumeratori (qui xs ... xxxxl) in diversi punti è necessario taggarlo 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 l'insieme di enumeratori. Quindi fai attenzione a 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 in una definizione di parametro:

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

Si potrebbe dire che riscrivere enum ovunque non sia conveniente e rende il codice un po 'strano. Hai ragione. Un vero tipo sarebbe meglio.

Questo è l'ultimo passo della nostra grande progressione verso il vertice. Aggiungendo solo un typedef trasformiamo la nostra enum in un tipo reale. Oh un'ultima cosa, typedef non è permesso 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 visto che qui in quel caso, non dobbiamo taggare 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 ObjectiveC con XCode, ti faccio scoprire alcune belle macro precedute da NS_ENUM. Questo dovrebbe aiutarti a definire facilmente le buone enumerazioni e inoltre aiuterà l'analizzatore statico a fare alcuni controlli interessanti prima di compilarlo.

Buon Enum!


Qui vengono dichiarate tre cose: viene dichiarato un tipo enumerato anonimo, ShapeType viene dichiarato typedef per ShapeType anonima e i tre nomi kCircle , kRectangle e kOblateSpheroid vengono dichiarati come costanti integrali.

Let's abbattere questo. 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 parola chiave enum . 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 utilizzare la parola chiave enum 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 usare enum tagname con la parola chiave enum , possiamo rendere l' enum anonimo e solo dichiararlo con il nome typedef:

typedef enum { ... } tagname;

Ora, in questo caso, stiamo dichiarando che ShapeType è un nome typedef di un'enumerazione anonima. ShapeType è in realtà solo un tipo integrale e deve essere utilizzato solo per dichiarare le variabili che contengono uno dei valori elencati nella dichiarazione (ovvero, kCircle , kRectangle e kOblateSpheroid ). È tuttavia possibile assegnare una variabile ShapeType a un altro valore mediante fusione, quindi è necessario prestare attenzione durante la lettura dei valori enum.

Infine, kCircle , kRectangle e kOblateSpheroid sono dichiarati come costanti integrali nello spazio dei nomi globale. Poiché non sono stati specificati valori specifici, vengono assegnati a interi consecutivi a partire da 0, quindi kCircle è 0, kRectangle è 1 e kOblateSpheroid è 2.


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

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

WORKDAYS today = Monday;

Quanto sopra è solo un'enumerazione di tag shapeType.


Un tipo definito dall'utente che ha i valori possibili di kCircle , kRectangle o kOblateSpheroid . I valori all'interno dell'enum (kCircle, ecc.) Sono visibili al di fuori dell'enum, però. È importante tenerlo a mente ( int i = kCircle; è valido, ad esempio).


enum è usato per assegnare valore agli elementi enum che non possono essere fatti in struct. Quindi ogni volta invece di accedere alla variabile completa possiamo farlo con il valore che assegniamo alle variabili in enum. Di default inizia con 0 assegnamento ma possiamo assegnargli qualsiasi valore e alla variabile successiva in enum verrà assegnato un valore del valore precedente +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 una sostituzione. Non è in grado di limitare tutte le condizioni dello stato. Quando lo stato è assegnato a 5, il programma sarà sbagliato, perché non c'è stato corrispondente. Ma il compilatore non ha intenzione di avvertire STATE = 5

Quindi è meglio usare così

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

SampleState state = SampleStateGood;

Aggiornamento per modifica a 64 bit: in base a Apple docs sulle modifiche a 64 bit,

Anche le enumerazioni vengono digitate: nel compilatore LLVM, i tipi enumerati possono definire la dimensione dell'enumerazione. Ciò significa che alcuni tipi enumerati possono anche avere una dimensione più grande di quanto previsto. La soluzione, come in tutti gli altri casi, è di non fare supposizioni sulla dimensione del tipo di dati. Invece, assegna qualsiasi valore enumerato a una variabile con il tipo di dati appropriato

Quindi devi creare enum con tipo come la seguente sintassi se supporti 64-bit.

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

o

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

In caso contrario, verrà Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType avviso poiché la Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType

Aggiornamento per la programmazione rapida:

In rapido, c'è un cambio di sintassi.

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

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;




typedef