Objective-C中的类型定义枚举是什么?

我不认为我从根本上理解enum是什么,什么时候使用它。

例如:

typedef enum {kCircle,kRectangle,kOblateSpheroid} ShapeType;

这里真正声明的是什么?

459305 次浏览

用户定义的类型,其值可能为kCirclekRectanglekOblateSpheroid。但是,枚举内部的值(kCircle等)在枚举外部是可见的。记住这一点很重要(例如,第3条是有效的)。

这里声明了三件事:声明了匿名枚举类型,将ShapeType声明为该匿名枚举的类型定义,将kCirclekRectanglekOblateSpheroid三个名称声明为整型常量。

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

enum tagname { ... };

这声明了一个标记为tagname的枚举。在C和Objective-C(但不是 c++)中,任何对必须的引用都以enum关键字开头。例如:

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 tagnameenum关键字,我们可以让enum匿名,只声明它与typedef名称:

typedef enum { ... } tagname;

现在,在本例中,我们将ShapeType声明为匿名枚举的类型定义名称。ShapeType实际上只是一个整型,应该只用于声明包含声明中列出的值之一的变量(即kCirclekRectanglekOblateSpheroid之一)。不过,您可以通过强制转换为ShapeType变量分配另一个值,因此在读取enum值时必须小心。

最后,kCirclekRectanglekOblateSpheroid在全局名称空间中声明为整数常量。由于没有指定特定的值,它们被分配给以0开头的连续整数,因此kCircle是0,kRectangle是1,kOblateSpheroid是2。

枚举声明了一组有序值——typedef只是给它加了一个方便的名字。第一个元素是0等等。

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

上面只是shapeType标记的枚举。

Apple从Xcode 4.4开始就建议这样定义枚举:

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

它们还提供了一个方便的宏NS_ENUM:

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

这些定义提供了更强的类型检查和更好的代码补全。我找不到NS_ENUM的官方文件,但你可以看&;Modern objective - c &;来自2012年全球开发者大会第一届会议的视频。


< p > # 0

.链接到正式文档在这里

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

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

此枚举被称为匿名,因为您没有符号来命名它。但它仍然是完全正确的。就像这样用

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

好的。生活是美丽的,一切都很顺利。但是有一天你需要重用这个枚举来定义一个新变量来存储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 enumenum 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;

可以说,在所有地方重写枚举并不方便,而且会使代码看起来有点奇怪。你说得对。真正的类型会更好。

这是我们向顶峰伟大前进的最后一步。通过添加typedef,我们可以将枚举转换为实类型。最后一点,typedef在类中是不允许的。然后在上面定义你的类型。这样做:

// enum definitionenum sizes { xs,s,m,l,xl,xxl,xxxl,xxxxl };typedef enum sizes size_type
@interface myClass {...size_type myGrandMotherDressSize, myGrandFatherPantSize;...}

记住,标记是可选的。在这种情况下,我们不标记枚举数,而只是定义一个新类型。那我们就不再需要它了。

// enum definitiontypedef enum { xs,s,m,l,xl,xxl,xxxl,xxxxl } size_type;
@interface myClass : NSObject {...size_type myGrandMotherDressSize, myGrandFatherPantSize;...}@end

如果你在Objective-C中使用XCode开发,我会让你发现一些以NS_ENUM为前缀的宏。这将帮助您轻松地定义好的枚举,而且还将帮助静态分析器在编译之前为您做一些有趣的检查。

Enum好!

typedef用于重新定义现有变量类型的名称。它提供了短&调用数据类型的有意义的方式。例句:< / p >

typedef unsigned long int TWOWORDS;

这里,unsigned long int类型被重新定义为TWOWORDS类型。因此,我们现在可以声明unsigned long int类型的变量:

TWOWORDS var1, var2;

而不是

unsigned long int var1, var2;
typedef enum {kCircle,kRectangle,kOblateSpheroid} ShapeType;

然后你可以这样使用它:-

 ShapeType shape;

而且

 enum {kCircle,kRectangle,kOblateSpheroid}ShapeType;

现在你可以这样使用它:-

enum ShapeType shape;

Update for 64位Change:根据苹果公司的文档关于64位的变化,

枚举也是类型化的:在LLVM编译器中,枚举类型可以定义枚举的大小。这意味着一些枚举类型的大小也可能比您期望的要大。的和其他情况一样,解是对a不做任何假设数据类型的大小。相反,将任何枚举值赋给变量使用正确的数据类型

因此,如果您支持64位,则必须按照下面的语法创建类型为

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

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

否则,它将导致警告为Implicit conversion loses integer precision: NSUInteger (aka 'unsigned long') to ShapeType

swift编程更新:

在swift中,有一个语法变化。

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

Enum用于为枚举元素赋值,这在struct中无法完成。因此,每次访问完整变量时,我们可以通过在enum中分配给变量的值来完成。默认情况下,它以0赋值开始,但我们可以为它赋任何值,enum中的下一个变量将被赋值为前一个值+1。

typedef允许程序员将一种Objective-C类型定义为另一种。例如,

计数器;将Counter类型定义为等效于int类型。这极大地提高了代码的可读性。

类型定义是C和c++中的关键字。它用于为基本数据类型(char, int, float, double, struct &enum)创建新名称。

typedef enum {kCircle,kRectangle,kOblateSpheroid} ShapeType;

这里它创建了枚举数据类型ShapeType &我们可以为枚举类型ShapeType编写新的名称,如下所示

ShapeType shape1;ShapeType shape2;ShapeType shape3;

您可以使用下面的格式,原始默认值从0开始,所以

  • kCircle是0,
  • kRectangle是1,
  • kOblateSpheroid是2。

您可以指定自己的特定起始值。

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 2int STATE = STATE_OTHER

定义没有约束。这只是一个简单的代换。它不能限制国家的所有条件。当STATE被赋值为5时,程序将出错,因为没有匹配的状态。但是编译器不会警告STATE = 5

所以这样用比较好

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