【问题标题】:What is a typedef enum in Objective-C?Objective-C 中的 typedef 枚举是什么?
【发布时间】:2010-10-16 23:45:19
【问题描述】:

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

例如:

typedef enum {
    kCircle,
    kRectangle,
    kOblateSpheroid
} ShapeType;

这里真正声明了什么?

【问题讨论】:

  • 用户定义的类型是否称为“枚举”?这就是我的想法,直到我遇到具有多个 typedef 枚举声明的代码。
  • 不,用户定义的类型是 ShapeType。阅读 typedef:en.wikipedia.org/wiki/Typedef
  • Objective-C 中的 typedef 与 C 中的 typedef 完全相同。Objective-C 中的 enum 与 C 中的 enum 完全相同。这声明了一个具有三个常量 kCircle = 0,kRectangle = 1 和 kOblateSpheroid = 2,并将枚举类型命名为 ShapeType。如果你不知道“typedef”和“enum”是什么意思,买一本关于 C 的书。

标签: objective-c enums typedef


【解决方案1】:

这里声明了三件事:声明了一个匿名枚举类型,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关键字,可以创建一个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 变量分配另一个值,因此在读取枚举值时必须小心。

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

【讨论】:

  • 很好的解释 - 只是补充一点,结构遵循 C 中类似的命名规则(不确定 Objective-C)。
  • Objective-C 是 C 的适当超集。C 中的所有 C 结构命名规则在 Objective-C 中同样有效。
  • 太棒了。我可以只使用 C++ 风格的枚举,也不需要编写枚举 :)
  • 如果声明枚举的文件是 .mm 文件而不是 .m,则可以使用 C++ 样式枚举。 Objective-C++ 功能强大得离谱。
  • 一旦你明白了这个答案,就值得看看新的 NS_ENUM 和 NS_OPTIONS。教程在这里:nshipster.com/ns_enum-ns_options 和所以在这里:stackoverflow.com/questions/14080750/…
【解决方案2】:

Apple 建议从 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 会议here 的“现代 Objective-C”视频。


更新
官方文档链接here

【讨论】:

【解决方案3】:

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

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

WORKDAYS today = Monday;

以上只是shapeType标签的枚举。

【讨论】:

    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      64 位更改更新: 根据apple docs关于64位的改动,

      Enumerations Are Also Typed :在 LLVM 编译器中,枚举类型可以 定义枚举的大小。这意味着一些枚举 types 的大小也可能比您预期的要大。这 与所有其他情况一样,解决方案是不对 数据类型的大小。相反,将任何枚举值分配给变量 具有正确的数据类型

      因此,如果您支持 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 中,语法发生了变化。

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

      【讨论】:

      【解决方案6】:

      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),则必须使用唯一名称对其进行标记。第二次使用此设置时,您只需使用标签。但不要忘记,这个标签不会替换枚举词,而只是替换枚举数的集合。然后照常注意使用枚举。像这样:

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

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

      这是我们向顶峰迈进的最后一步。通过添加一个 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 为前缀的好宏。这应该可以帮助您轻松地定义好的枚举,而且还可以帮助静态分析器在编译之前为您做一些有趣的检查。

      很好的枚举!

      【讨论】:

      • 我一直在想“为什么有人会回答一个已经回答和接受的问题”。男孩,我一直都错了!这是最好的答案,可以帮助像我这样的初学者!
      【解决方案7】:

      typedef 可用于重新定义现有变量类型的名称。它提供了调用数据类型的简短而有意义的方式。 例如:

      typedef unsigned long int TWOWORDS;
      

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

      TWOWORDS var1, var2;
      

      而不是

      unsigned long int var1, var2;
      

      【讨论】:

        【解决方案8】:
        typedef enum {
        kCircle,
        kRectangle,
        kOblateSpheroid
        } ShapeType;
        

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

         ShapeType shape;
        

         enum {
            kCircle,
            kRectangle,
            kOblateSpheroid
        } 
        ShapeType;
        

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

        enum ShapeType shape;
        

        【讨论】:

          【解决方案9】:

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

          【讨论】:

            【解决方案10】:

            你可以使用下面的格式,Raw默认值从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
            

            【讨论】:

              【解决方案11】:

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

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

              【讨论】:

                【解决方案12】:

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

                typedef enum {
                    kCircle,
                    kRectangle,
                    kOblateSpheroid
                } ShapeType;
                

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

                ShapeType shape1; 
                ShapeType shape2; 
                ShapeType shape3;
                

                【讨论】:

                  【解决方案13】:

                  枚举可以减少多种“错误”,让代码更易于管理

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

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

                  所以最好这样使用

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

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多