objective c - Enumeración de Objective-C, NS_ENUM & NS_OPTIONS
cocoa enums (2)
¿Cuál es la forma correcta de crear una enumeración con un tipo específico en Objective-C? ¿Cómo funcionan NS_ENUM y NS_OPTIONS? ¿NS_OPTIONS se utilizan para máscaras, como NSAutorizing? Gracias.
Code from NSObjCRuntime.h
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#define NS_OPTIONS(_type, _name) _type _name; enum : _type
Ejemplo de NSHipster . NS_OPTIONS se usa de manera similar, pero para enumeraciones que normalmente serían una máscara de bits
en lugar de
typedef enum {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
} UITableViewCellStyle;
o
typedef enum {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
};
typedef NSInteger UITableViewCellStyle;
hacer esto:
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
};
un ejemplo NS_OPTIONS enumeración:
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
Hay una diferencia entre los dos, excepto que infieren diferentes tipos de enumeraciones.
Cuando se compilan en el modo Objective-C ++, generan un código diferente:
Este es el código original:
typedef NS_OPTIONS(NSUInteger, MyOptionType) {
MyOptionType1 = 1 << 0,
MyOptionType2 = 1 << 1,
};
typedef NS_ENUM(NSUInteger, MyEnumType) {
MyEnumType1 = 1 << 0,
MyEnumType2 = 1 << 1,
};
este es el código cuando las macros se expanden en la compilación de Objective-C
:
typedef enum MyOptionType : NSUInteger MyOptionType; enum MyOptionType : NSUInteger {
MyOptionType1 = 1 << 0,
MyOptionType2 = 1 << 1,
};
typedef enum MyEnumType : NSUInteger MyEnumType; enum MyEnumType : NSUInteger {
MyEnumType1 = 1 << 0,
MyEnumType2 = 1 << 1,
};
este es el código cuando las macros se expanden en la compilación de Objective-C++
:
typedef NSUInteger MyOptionType; enum : NSUInteger {
MyOptionType1 = 1 << 0,
MyOptionType2 = 1 << 1,
};
typedef enum MyEnumType : NSUInteger MyEnumType; enum MyEnumType : NSUInteger {
MyEnumType1 = 1 << 0,
MyEnumType2 = 1 << 1,
};
¿Ves la diferencia de NS_OPTIONS entre dos modos?
HERE IS THE REASON
:
Hay una nueva característica en C ++ 11, puede declarar un tipo para su enumeración, antes de eso, el tipo que contiene la enumeración es decidido por el compilador de acuerdo con el mayor valor de enumeración.
Por lo tanto, en C ++ 11, ya que puede decidir el tamaño de su enumeración por sí mismo, puede reenviar declarar enumerados sin realmente definirlos, de esta manera:
//forward declare MyEnumType
enum MyEnumType: NSInteger
//use myEnumType
enum MyEnumType aVar;
//actually define MyEnumType somewhere else
enum MyEnumType: NSInteger {
MyEnumType1 = 1 << 1,
MyEnumType2 = 1 << 2,
}
Esta característica es útil, y Objective-C importa esta característica, pero trae un problema, al hacer un cálculo a nivel de bits, como este:
enum MyEnumType aVar = MyEnumType1 | MyEnumType2;
Este código no se puede compilar en C ++ / Objective-C ++, ya que aVar se considera de tipo NSInteger
pero MyEnumType1 | MyEnumType2
MyEnumType1 | MyEnumType2
es de tipo MyEnumType
, esta asignación no puede realizarse sin una conversión de tipos , C ++ prohíbe la conversión de tipos implícita
En este momento, necesitamos que NS_OPTIONS, NS_OPTIONS retrocedan a la enumeración antes de C ++ 11, para que no haya MyEnumType
, MyEnumType
es solo otro nombre más para NSInteger
, por lo que el código como
enum MyEnumType aVar = MyEnumType1 | MyEnumType2;
se compilará, ya que está asignando NSInteger
a NSInteger
.