objective c - ¿Qué es una enumeración typedef en Objective-C?




enums (10)

Apple recomienda definir enums como este desde Xcode 4.4:

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

También proporcionan una macro útil NS_ENUM:

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

Estas definiciones proporcionan una comprobación de tipos más sólida y una mejor terminación del código. No pude encontrar una documentación oficial de NS_ENUM, pero puedes ver el video "Modern Objective-C" de la sesión WWDC 2012 here .

ACTUALIZACIÓN: Enlace a la documentación oficial here .

No creo que entienda fundamentalmente qué es una enum y cuándo usarla.

Por ejemplo:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

¿Qué está siendo realmente declarado aquí?


Aquí se declaran tres cosas: se declara un tipo anónimo enumerado, se declara ShapeType como typedef para esa enumeración anónima, y ​​los tres nombres kCircle , kRectangle y kOblateSpheroid se declaran como constantes integrales.

Vamos a romper eso. En el caso más simple, una enumeración puede ser declarada como

enum tagname { ... };

Esto declara una enumeración con la etiqueta tagname . En C y en Objective-C (pero no en C ++), cualquier referencia a esto debe ir precedida de la palabra clave enum . Por ejemplo:

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

Para evitar tener que usar la palabra clave enum todas partes, se puede crear un typedef:

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

Esto se puede simplificar en una sola línea:

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

Y, finalmente, si no necesitamos poder usar enum tagname con la palabra clave enum , podemos hacer que la enum anónima y solo declararla con el nombre typedef:

typedef enum { ... } tagname;

Ahora, en este caso, estamos declarando que ShapeType es un nombre escrito de una enumeración anónima. ShapeType es realmente solo un tipo integral, y solo debe usarse para declarar variables que contienen uno de los valores listados en la declaración (es decir, uno de kCircle , kRectangle , y kOblateSpheroid ). Sin embargo, puede asignar otro valor a la variable ShapeType mediante el lanzamiento, por lo que debe tener cuidado al leer los valores de enumeración.

Finalmente, kCircle , kRectangle y kOblateSpheroid se declaran como constantes integrales en el espacio de nombres global. Como no se especificaron valores específicos, se asignan a enteros consecutivos que comienzan con 0, por lo que kCircle es 0, kRectangle es 1 y kOblateSpheroid es 2.


Enum es el tipo de datos definido por el usuario. TIPOS DE DATOS ENUMERADOS Las variables de tipos de datos enumerados solo pueden asumir valores que se han declarado previamente.

enum month { jan = 1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec };
enum month this_month;

this_month = feb;

En la declaración anterior, el mes se declara como un tipo de datos enumerados. Consiste en un conjunto de valores, jan a dec. Numéricamente, a jan se le da el valor 1, feb el valor 2, y así sucesivamente.

La variable this_month se declara del mismo tipo que mes, luego se le asigna el valor asociado a feb. A este mes no se le puede asignar ningún valor fuera de los especificados en la lista de inicialización para la declaración del mes.


Enum puede reducir muchos tipos de "errores" y hacer que el código sea más manejable

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

La definición no tiene restricciones. Es simplemente una sustitución. No es capaz de limitar todas las condiciones del estado. Cuando el ESTADO se asigna a 5, el programa será incorrecto, porque no hay un estado coincidente. Pero el compilador no avisará al ESTADO = 5

Así que es mejor usar así

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

SampleState state = SampleStateGood;

Se puede usar en el formato a continuación, el valor predeterminado bruto desde 0, por lo que

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

Puede asignar su propio valor de inicio específico.

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

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

Un tipo definido por el usuario que tiene los valores posibles de kCircle , kRectangle o kOblateSpheroid . Sin embargo, los valores dentro de la enumeración (kCircle, etc.) son visibles fuera de la enumeración. Es importante tener esto en cuenta ( int i = kCircle; es válido, por ejemplo).


Una enumeración declara un conjunto de valores ordenados; typedef simplemente agrega un nombre práctico a esto. El 1er elemento es 0 etc.

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

WORKDAYS today = Monday;

Lo anterior es solo una enumeración de las etiquetas shapeType.


enum se usa para asignar valor a los elementos enum que no se pueden hacer en struct. Entonces, en lugar de acceder a la variable completa, podemos hacerlo por el valor que asignamos a las variables enumeración. Por defecto, comienza con una asignación de 0, pero podemos asignarle cualquier valor y a la siguiente variable enumeración se le asignará un valor, el valor anterior +1.


Actualización para el cambio de 64 bits: Según los documentos de Apple sobre los cambios de 64 bits,

Las enumeraciones también se escriben: en el compilador LLVM, los tipos enumerados pueden definir el tamaño de la enumeración. Esto significa que algunos tipos enumerados también pueden tener un tamaño mayor que el esperado. La solución, como en todos los demás casos, es no hacer suposiciones sobre el tamaño de un tipo de datos. En su lugar, asigne cualquier valor enumerado a una variable con el tipo de datos adecuado

Por lo tanto, debe crear la enumeración con el tipo como se indica a continuación en la sintaxis si admite 64 bits.

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

o

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

De lo contrario, dará lugar a una advertencia ya que la Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType

Actualización para la programación rápida:

En veloz, hay un cambio de sintaxis.

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

typedef enum {
kCircle,
kRectangle,
kOblateSpheroid
} ShapeType;

entonces puedes usarlo como:

 ShapeType shape;

y

 enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} 
ShapeType;

Ahora puedes usarlo como:

enum ShapeType shape;




typedef