2009-11-02 21 views
29

¿Es posible recorrer valores enum en Objective-C?bucle a través de los valores enum

+0

reetiquetado: esto es (que yo sepa) una pregunta C pura. Obtendrás más respuesta con el etiquetado más general. –

+14

También responde la pregunta para las personas que lo buscan en Obj-C. Se agregó esa etiqueta de regreso. – pbh101

Respuesta

7

Si enumeración se define como sigue:

enum Direction { East, West, North, South}; 

Puede recorrer esta manera:

for (int direction = East; direction <= South; ++direction) 
{ 
    /* Do something with Direction 
} 
+0

Nunca he hecho esto, así que tengo algunas preguntas. ¿No debería ser Direction.East y Direction.South? Además, ¿no debería la condición ser dirección <= Dirección.Sur? De nuevo, nunca he hecho esto, no estoy tratando de corregirte, solo me gustaría aprender. –

+3

¿Hay una mejor manera de hacer esto? Es curioso, pero parece que depende del orden de las declaraciones de los valores enum, es, en el mejor de los casos, frágil. –

+0

@blaenk: creo que estás confundiendo estructuras con enumeraciones. – pxl

36

Dada

enum Foo {Bar=0,Baz,...,Last}; 

se puede iterar los elementos como:

for(int i=Bar; i<=Last; i++) { 
    ... 
} 

Tenga en cuenta que esto expone la naturaleza realmente-solo-un-int de una C enum. En particular, puede ver que una C enum no proporciona seguridad de tipo, ya que puede usar un int en lugar de un valor enum y viceversa. Además, esto depende del orden de declaración de los valores enum: frágil, por decir lo menos. Además, vea el comentario de Chuck; si los elementos enumerados no son contiguos (por ejemplo, porque especificó valores explícitos y no secuenciales para algunos elementos), esto no funcionará en absoluto. Yikes.

+8

También requiere que todos los elementos en la enumeración sean contiguos. Pero es lo mejor que obtendrás – Chuck

+0

no reconoce Foo en el para looo para mí. – Frank

+6

Es un nitpick puro, pero se deletrea 'viceversa'. – new123456

8

Es un poco complicado (como todo el concepto, así que ... eh ...) pero si vas a hacer esto varias veces, y quieres ser capaz de lidiar con la posibilidad de no -enumeraciones contiguas, puede crear una matriz (constante global) y tener (para usar el ejemplo de ennukiller) Indicaciones de direcciones [4] = {Este, Oeste, Norte, Sur}; y luego en el bucle se puede hablar de direcciones [i] en lugar de la iteración directamente sobre las direcciones a sí mismos ...

Como ya he dicho, es feo, pero es un poco menos frágil que pienso ...

+0

me queda bien. ¿Hay alguna forma de que podamos agregar algún tipo de macro que automáticamente genere C-arrays para cada tipo de enumeración que declaramos? – ArtOfWarfare

+1

@ArtOfWarfare Uso esto todo el tiempo: '#define ENUM (tipo, ...) enum _ ## tipo {__VA_ARGS__}; enum _ ## type type ## s [] = {__VA_ARGS__} ', aunque eso solo funcionará para los contiguos. No uso enumeraciones no contiguas, porque eso me indica un mal diseño. También tengo 'typedef struct _list List;', 'typedef enum _direction Direction' en todas partes en mi código C que usa esta macro, por lo que prefijo _ al tipo. 'ENUM (direction, NORTH, EAST, SOUTH, WEST);' da como resultado 'enum _direction {NORTH, EAST, SOUTH, WEST}; enum _direction directions = {NORTH, EAST, SOUTH, WEST}; 'Me gusta. –

1

me gusta lo que tengo de aquí Iteration over enum in Objective C?

typedef enum { ENUM1=0, ENUM2, ENUM3, ENUM4 , TOTAL } ; 


for (int i=ENUM1 ; i<TOTAL; i++) 
{} 

esa manera se puede seguir añadiendo enumeraciones más tarde y no afecta a sus bucles?

5

En busca de esto, inventé la siguiente solución que cumplía con mis propios requisitos. Pensé que lo publicaría aquí para las personas que buscan algo similar.

Di que tengo un enum.

typedef NS_ENUM (NSInteger, ISDirection) { 
    ISDirectionUp, 
    ISDirectionDown, 
    ISDirectionLeft, 
    ISDirectionRight 
}; 

Para poder recorrerlo, defino la siguiente macro del preprocesador.

#define ISDirectionAllAsDir ISDirection dir = ISDirectionUp; dir <= ISDirectionRight; dir++ 

Luego uso dentro de un bucle, como tal:

for(ISDirectionAllAsDir) { 
    NSLog(@"Direction %d", dir); 
} 

Esto pone a la lógica para iterar en un lugar (la macro) que aumenta código de mantenimiento.

3

Para enumeraciones no contiguas puede iterar sobre los valores válidos haciendo:

enum { 
    value_one = 0, 
    value_two = 1, 
    value_three = 3, 
    value_max 
} 
for (i = value_one; i < value_max; i++) 
{ 
    switch(i) 
    { 
     case value_one: 
     case value_two: 
     case value_three: 
     case value_four: 
     { 
      /* ... Do something with valid enum value ... */ 
     } 
     break; 
     default: 
      /* Found an invalid enum entry; ignore it */ 
     break; 
    } 
} 
+0

En este caso, no usaría ningún bucle. Simplemente deje los bloques de la caja del interruptor uno tras otro, será más limpio y, a veces más eficiente. –

+0

Claro, estoy completamente de acuerdo con usted y no escribiría esto en el código de producción; la única razón por la que encerré el interruptor dentro de un bucle es porque eso es lo que estaba pidiendo el cartel original;) ​​ –

2

La longitud (número de elementos) de cualquier enumeración puede determinarse por conseguir la variedad de nombres en la enumeración y la utilización de la la longitud de la matriz Use el método GetNames de Enum. Enum.GetNames (enumType) .Length.

{ 
enum Pig { Snort, Sty, Oink, Curly }; 
const int Pig_Count = Enum.GetNames(typeof(Pig)).Length; 
} 
-3
enum direction = {South, North, East, West}; 

//this is used to loop through enum in the while loop, and will contain the enum length when the while loop finishes. 
int index = 0; 
while(direction[index] != null){ 
    index++; 
} 

//loop through all the values in the enum 
for (int i = 0; i < index; i++){ 
    //your code here, 'direction[index]' will return the enum name 
} 
+2

La publicación original (OP) trataba de iterar a través de enumeraciones. No hay nada en su respuesta que aborde la pregunta original. Por favor edite su respuesta para responder a la pregunta. – rothloup

+0

el código anterior registrará cada nombre enum en la "dirección" enum. ¿Cómo responde esto ahora la pregunta? – allanjwalter

+0

Quizás deba agregar alguna explicación o código para indicar que "dirección" es la enumeración que está registrando. Tal vez para un programador experimentado es obvio desde su código, pero un codificador como ese no habría publicado la pregunta en primer lugar. Agregar una pequeña explicación ayudará a aclarar su respuesta y hacerla más útil para cualquier persona que se le ocurra. – rothloup