Objective-C中的typedef枚举是什么?

Objective-C中的typedef枚举是什么?,objective-c,enums,typedef,Objective C,Enums,Typedef,我认为我根本不了解什么是enum,以及何时使用它 例如: typedef enum { kCircle, kRectangle, kOblateSpheroid } ShapeType; enum tagname x; // declare x of type 'enum tagname' tagname x; // ERROR in C/Objective-C, OK in C++ 这里真正声明的是什么?一种用户定义的类型,其可能值为kCircle、kRecta

我认为我根本不了解什么是
enum
,以及何时使用它

例如:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;
enum tagname x;  // declare x of type 'enum tagname'
tagname x;  // ERROR in C/Objective-C, OK in C++

这里真正声明的是什么?

一种用户定义的类型,其可能值为
kCircle
kRectangle
koblateSpropherod
。但是,枚举内部的值(kCircle等)在枚举外部可见。记住这一点很重要(
int i=kCircle;
例如是有效的)。

这里声明了三件事:一个匿名枚举类型被声明,
ShapeType
被声明为该匿名枚举的typedef,三个名称
kCircle
kRectangle
,和
kOblateSpheroid
被声明为整数常量

让我们把它分解一下。在最简单的情况下,枚举可以声明为

enum tagname { ... };
这声明了一个带有标记名
的枚举。在C和Objective-C(但不是C++)中,对它的任何引用前面都必须加上
enum
关键字。例如:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;
enum tagname x;  // declare x of type 'enum tagname'
tagname x;  // ERROR in C/Objective-C, OK in C++
为了避免到处使用
enum
关键字,可以创建一个typedef:

enum tagname { ... };
typedef enum tagname tagname;  // declare 'tagname' as a typedef for 'enum tagname'
这可以简化为一行:

typedef enum tagname { ... } tagname;  // declare both 'enum tagname' and 'tagname'
最后,如果我们不需要将
enum标记名
enum
关键字一起使用,我们可以使
enum
匿名,并且只使用typedef名称声明它:

typedef enum { ... } tagname;
现在,在本例中,我们将
ShapeType
声明为匿名枚举的类型定义名称
ShapeType实际上只是一个整型,只应用于声明包含声明中列出的一个值的变量(即
kCircle
KretAngle
kOblateSpheroid
中的一个)。但是,您可以通过强制转换为
ShapeType
变量指定另一个值,因此在读取枚举值时必须小心


最后,
kCircle
kRectangle
koblateSpropherod
被声明为全局命名空间中的整型常量。由于没有指定特定的值,它们被分配给从0开始的连续整数,因此
kCircle
为0,
kRectangle
为1,
kOblateSpheroid
为2。

枚举声明了一组有序值-typedef只是为其添加了一个方便的名称。第一个元素是0等

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

WORKDAYS today = Monday;

以上只是shapeType标记的枚举。

苹果建议这样定义枚举,因为Xcode 4.4

typedef enum ShapeType : NSUInteger {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;
它们还提供了一个方便的宏
NS_ENUM

typedef NS_ENUM(NSUInteger, ShapeType) {
    kCircle,
    kRectangle,
    kOblateSpheroid
};
这些定义提供了更强的类型检查和更好的代码完成。我找不到
NS_ENUM
的官方文档,但您可以观看WWDC 2012年会议的“Modern Objective-C”视频


更新
链接到官方文档。

枚举(枚举的缩写)用于枚举一组值(枚举数)。值是由符号(词)表示的抽象事物。 例如,基本枚举可以是

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl };
此枚举称为匿名,因为您没有符号来命名它。但这仍然是完全正确的。就这样用吧

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
typedef enum SampleState {
    SampleStateGood  = 0,
    SampleStateBad,
    SampleStateOther
} SampleState;

SampleState state = SampleStateGood;
嗯。生活是美好的,一切都很顺利。但有一天,您需要重用此枚举来定义一个新变量来存储myGrandFatherPantSize,然后编写:

enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandMotherDressSize;
enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } myGrandFatherPantSize;
但随后出现了一个编译器错误“重新定义枚举数”。事实上,问题是编译器不确定您是否第一个枚举,第二个枚举是否描述了相同的内容

然后,如果您想在多个地方重复使用同一组枚举数(这里是xs…xxxxl),则必须使用唯一的名称对其进行标记。第二次使用此集合时,只需使用标记即可。但别忘了,这个标记并不会替换枚举词,而只是替换一组枚举数。然后注意像往常一样使用enum。像这样:

// 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;
您也可以在参数定义中使用它:

// Observe that here, I still use the enum
- (void) buyANewDressToMyGrandMother:(enum sizes)theSize;
可以说,到处重写enum并不方便,而且会使代码看起来有点奇怪。你是对的。一个真正的类型会更好

这是我们向首脑会议迈进的最后一步。通过添加一个typedef,让我们将枚举转换为一个实类型。哦,最后一件事,typedef在你的课堂上是不允许的。然后在上面定义您的类型。这样做:

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

@interface myClass {
   ...
   size_type myGrandMotherDressSize, myGrandFatherPantSize;
   ...
}
请记住,标记是可选的。因此,在这种情况下,我们不标记枚举数,而只是定义一个新类型。那我们真的不再需要它了

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

@interface myClass : NSObject {
  ...
  size_type myGrandMotherDressSize, myGrandFatherPantSize;
  ...
}
@end
如果您是使用XCode在Objective-C中开发的,我会让您发现一些带有NS_ENUM前缀的漂亮宏。这将帮助您轻松定义好的枚举,而且还将帮助静态分析器在编译之前为您做一些有趣的检查


好的枚举

typedef
用于重新定义现有变量类型的名称。它提供了调用数据类型的简短而有意义的方法。 e、 g:

这里,类型unsigned long int被重新定义为类型twoords。因此,我们现在可以通过编写

TWOWORDS var1, var2;
而不是

unsigned long int var1, var2;
然后您可以像这样使用它:-

 ShapeType shape;

现在您可以像这样使用它:-

enum ShapeType shape;

64位更改的更新: 根据大约64位的变化

枚举也是类型化的:在LLVM编译器中,枚举类型可以 定义枚举的大小。这意味着,一些 类型的大小也可能比您预期的大。这个 和所有其他情况一样,解决方案是不假设 数据类型的大小。而是将任何枚举值赋给变量 使用正确的数据类型

因此,如果您支持64位,则必须使用以下语法创建类型为的枚举

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

否则,它将导致警告,因为
隐式转换将丢失整数精度:NSUInt
typedef enum ShapeType : NSUInteger {
   kCircle,
   kRectangle,
   kOblateSpheroid
} ShapeType;
enum ControlButtonID: NSUInteger {
        case kCircle , kRectangle, kOblateSpheroid
    }
typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;
ShapeType shape1; 
ShapeType shape2; 
ShapeType shape3;
typedef enum : NSUInteger {
    kCircle, // for your value; kCircle = 5, ...
    kRectangle,
    kOblateSpheroid
} ShapeType;

ShapeType circleShape = kCircle;
NSLog(@"%lu", (unsigned long) circleShape); // prints: 0
#define STATE_GOOD 0
#define STATE_BAD 1
#define STATE_OTHER 2
int STATE = STATE_OTHER
typedef enum SampleState {
    SampleStateGood  = 0,
    SampleStateBad,
    SampleStateOther
} SampleState;

SampleState state = SampleStateGood;