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

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

例如:

 typedef enum { kCircle, kRectangle, kOblateSpheroid } ShapeType; 

这里真的宣布什么了?

这里声明了三件事情:声明匿名枚举types,将ShapeType声明为该匿名枚举的typedef,并将三个名称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关键字,可以创build一个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 tagname关键字来使用enum tagname ,那么我们可以使enum匿名,并且只声明typedef名称:

 typedef enum { ... } tagname; 

现在,在这种情况下,我们声明ShapeType是一个匿名枚举types的名字。 ShapeType实际上只是一个整型,只能用于声明保存声明中列出的值(即kCirclekRectanglekOblateSpheroid )的kOblateSpheroid 。 不过,您可以通过强制转换赋予一个ShapeTypevariables的另一个值,因此读取枚举值时必须小心。

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

苹果推荐从Xcode 4.4开始定义这样的枚举:

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

他们还提供了一个方便的macrosNS_ENUM:

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

这些定义提供更强的types检查和更好的代码完成。 我找不到NS_ENUM的官方文档,但是您可以在这里观看WWDC 2012会议上的“Modern Objective-C”video。

更新:链接到这里的官方文档。

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

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

以上只是枚举shapeType标签。

用户定义的types,它具有kCirclekRectanglekOblateSpheroid的可能值。 虽然枚举(kCircle等)内的值在枚举之外是可见的。 记住这一点非常重要(例如, int i = kCircle;是有效的)。

更新64位更改:根据有关64位更改的苹果文档 ,

枚举types也是如此:在LLVM编译器中,枚举types可以定义枚举的大小。 这意味着一些枚举types的大小也可能大于您的预期。 与所有其他情况一样,解决scheme是不对数据types的大小做任何假设。 相反,将任何枚举值赋给具有适当数据types的variables

因此,如果您支持64位,则必须使用以下语法的types创build枚举

 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

更新快速编程:

在迅速,有一个语法的变化。

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

枚举是用户定义的数据types。 枚举的数据types枚举的数据typesvariables只能假定先前已声明的值。

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

在上面的声明中,month被声明为枚举数据types。 它由一组值,1月至12月。 在数值上,jan的值是1,feb的值是2,依此类推。

variablesthis_month被声明为与月份相同的types,然后被分配与feb相关联的值。 This_month不能在月份声明的初始化列表中指定的值外分配任何值。

枚举(enumeration的缩写)用于枚举一组值(枚举器)。 值是由符号(一个词)表示的任何抽象的东西。 例如,一个基本的枚举可以是

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

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

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

好。 生活美好,一切顺利。 但有一天,你需要重用这个枚举来定义一个新的variables来存储myGrandFatherPantSize,然后你写:

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

但是,那么你有一个编译器错误“重新定义枚举器”。 其实问题是编译器不能确定你第一次枚举,第二次描述同样的事情。

那么如果你想在几个地方重复使用相同的一组枚举器(这里是xs … xxxxl),你必须用一个唯一的名字来标记它。 你第二次使用这个集合,你只需要使用标签。 但不要忘记,这个标签不会取代枚举字,而只是一组枚举数。 然后照常使用枚举。 喜欢这个:

 // 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; 

你可以说到处重写枚举不方便,代码看起来有点奇怪。 你是对的。 一个真正的types会更好。

这是我们进入峰会的最后一步。 通过添加一个typedef让我们把我们的enum转换成一个真正的types。 哦,最后一件事,typedef是不允许在你的class级。 然后在上面定义你的types。 像这样做:

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

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

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

如果你正在使用XCode开发ObjectiveC,我让你发现一些用NS_ENUM开头的macros。 这应该可以帮助您轻松定义好的枚举,而且还可以帮助静态分析器在编译之前为您做一些有趣的检查。

好的枚举!

typedef对重新定义现有variablestypes的名称很有用。 它提供了调用数据types的简短有意义的方法。 例如:

 typedef unsigned long int TWOWORDS; 

在这里,unsigned long inttypes被重新定义为TWOWORDStypes。 因此,我们现在可以通过编写来声明unsigned long inttypes的variables,

 TWOWORDS var1, var2; 

代替

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

那么你可以像这样使用它:

  ShapeType shape; 

  enum { kCircle, kRectangle, kOblateSpheroid } ShapeType; 

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

 enum ShapeType shape; 

枚举是用来分配值,不能在结构中的枚举元素。 所以每一次,而不是访问完整的variables,我们可以通过我们分配给枚举variables的值。 默认情况下,它从0赋值开始,但是我们可以给它赋值任何值,并且枚举中的下一个variables将赋值为前一个值+1。

typedef允许程序员将一个Objective-Ctypes定义为另一个。 例如,

typedef int Counter; 定义typesCounter与inttypes等价。 这极大地提高了代码的可读性。

Typedef是C和C ++中的一个关键字。 它用于为基本数据types(char,int,float,double,struct和enum)创build新名称。

 typedef enum { kCircle, kRectangle, kOblateSpheroid } ShapeType; 

在这里它创build枚举的数据typesShapeType ,我们可以为枚举typesShapeType写下新的名字,如下所示

 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