美文网首页ios学习积累
[iOS-Objective-C] 枚举

[iOS-Objective-C] 枚举

作者: 水止云起 | 来源:发表于2015-11-29 09:26 被阅读175次

参考资料

《编写高质量iOS与OS X代码的52个有效方法》中第5条:用枚举表示状态、选项、状态码

枚举类型的基本使用

枚举的作用在于规范并语义化的定义代码中的状态、选项等常量。枚举类型的定义以关键字enum开头,之后是枚举数据类型的名称,最后是在一对花括号内的选项标识符序列。 编译器会为枚举分配一个独有的编号,从0开始,每个枚举递增1。

enum  Direction {up, down, left, right};

实现枚举所用的数据类型取决于编译器。除了使用默认类型,还可以指明用何种“底层数据类型”来保存枚举类型的变量。

enum Direction : UNSInteger {up, down, left, right};

还可以不使用编译器所分配的序号,而是手工指定某个枚举成员所对应的值。如下例中将 up 的值设为1,而不使用编译器所分配的0。接下来的枚举值会在上一个的基础上递增1。

enum Direction {up = 1, down, left, right};

枚举的另一种使用方式是定义为按位掩码,当定义选项的时候,若这些选项可以彼此组合,则在设置特定的枚举值后,各选项间就可通过“按位或”来组合。因为每个枚举值所对应的二进制表示中,只有1个二进制位的值是1,所以多个选项“按位或”后的组合值是唯一的,且将某一选项与组合值做“按位与”操作,即可判断出组合值中是否包含该选项。

enum Direction {
   up = 1 << 0, 
   down = 1 << 1, 
   left = 1 << 2, 
   right = 1 << 3
};

使用关键字 typedef 重新定义枚举

然而声明或定义一个枚举类型变量的方式却不太简洁,仍然需要使用enum关键字,如:

enum  Direction {up, down, left, right};
enum Direction var1;

enum {up, down, left, right} var1;

为了简化枚举的声明,不需要每次都写enum,可以使用关键字typedef重新定义枚举类型

enum {up, down, left, right} Direction;
typedef enum Direction Direction;

之后就可以直接用 Direction 来代替完整的 enum Direction 了:

Direction var1, var2;

使用枚举的正确姿势

苹果对 Objective-C 语言支持了两个有关枚举的辅助弘,分别是NS_ENUMNS_OPTIONSNS_ENUM用来定义普通的枚举类型,NS_OPTIONS用来定义可组合选项的枚举类型。

typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};

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

这些宏是用#define预处理指令来定义的,具备向后兼容能力,如果目标平台的编译器支持新标准,那就使用新式语法,否则改用旧式语法。具体的定义如下:

#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum))
  #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
  #if (__cplusplus)
    #define NS_OPTIONS(_type, _name) _type _name; enum : _type
  #else
    #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
  #endif
#else
  #define NS_ENUM(_type, _name) _type _name; enum
  #define NS_OPTIONS(_type, _name) _type _name; enum
#endif

上述代码首先判断编译器是否支持新式枚举,如果不支持,那么NS_ENUMNS_OPTIONS都使用相同的老式语法来定义枚举:

typedef NSInteger Direction;
enum {up, down, left, right};

但是,旧式的语法无法告诉编译器重新定义的枚举类型与之后 enum 定义的整形值之间的联系。如果支持新特性,那么NS_ENUM宏所定义的枚举类型展开之后就是:

typedef enum UITableViewCellStyle : NSInteger UITableViewCellStyle;
enum UITableViewCellStyle : NSInteger {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};

根据是否要将代码按 C++ 编译,NS_OPTIONS宏的定义方式也有所不同。如果不按 C++ 编译,那么其展开方式就和NS_ENUM相同。若按 C++ 编译,则展开后的代码略有不同。原因在于,用按位或运算来操作两个枚举值时, C++ 编译模式的处理与非 C++ 模式不一样。在用或运算操作两个枚举值时, C++ 认为运算结果的数据类型应该是枚举的底层数据类型,而 C++ 不允许将这个底层类型“隐式转换”为枚举类型本身。如果想编译通过,就要将按位或操作的结果“显式转换”为枚举类型。所以,在 C++ 模式下应该用另一种方式定义NS_OPTIONS宏,以便省去类型转换操作。

鉴于此,凡是需要以按位或操作来组合的枚举都应使用NS_OPTIONS定义。若是枚举不需要互相组合,则应使用NS_ENUM来定义。

枚举在 switch 语句中的应用

当在 switch 语句中使用 enum 值时,不建议添加 default 分支。因为 enum 的选项分支已经包含了所有可能的情况,并不需要额外处理默认情况。而且,当之后添加新的状态时,编译器还会发出警告信息,提示新加入的状态并未在 switch 分支中处理。

相关文章

  • [iOS-Objective-C] 枚举

    参考资料 《编写高质量iOS与OS X代码的52个有效方法》中第5条:用枚举表示状态、选项、状态码 枚举类型的基本...

  • 01.优秀的Objective-C编码风格指南

    @(〓〓 iOS-Objective-C精选)[Objective-C 文章精选] 作者: Liwx 邮箱: 1...

  • iOS-Runtime01-基础结构isa以及相关知识(位运算、

    在笔者编写的iOS-Objective-C的本质中,我们已经了解到,所有的OC对象本质中都包含了一个isa指针,这...

  • C#枚举及与枚举常数的转换

    1、枚举的定义 2、枚举绑定到comboBox 3、枚举常数转换为枚举string转枚举 数字值转枚举

  • Swift 基础笔记 - 枚举

    枚举 OC定义和使用枚举 Swift定义枚举类型 Swift判断枚举类型 枚举成员类型

  • [iOS-Objective-C] 注释

    Cocoa 开发者间流传着一句格言,Objective-C 的冗长使得其代码就是有效的自我说明。有了[longMe...

  • [iOS-Objective-C] Runtime

    Objective-C 是 C 语言的扩展,加入了面向对象特性和 Smalltalk 式的消息传递机制,这些特性使...

  • [iOS-Objective-C] @property

    概念 @property,@synthesize都是编译器指令,在源文件被编译时,会被替换为相应的代码。@prop...

  • 枚举类

    1.枚举类型的定义: 枚举类型定义的一般形式为 enum 枚举名{//枚举值表枚举值1;枚举值2;...} 在枚举...

  • 10、枚举与闭包

    枚举 枚举和普通类相比有什么优势 枚举类型、枚举名称与枚举值 枚举的比较运算 两个枚举之间可以使用等值比较(==)...

网友评论

    本文标题:[iOS-Objective-C] 枚举

    本文链接:https://www.haomeiwen.com/subject/cmodhttx.html