NS_ENUM和NS_OPTIONS有什么区别?

tai*_*ino 30 cocoa objective-c ios

我在Xcode5中使用clang预处理了以下代码.

typedef NS_ENUM(NSInteger, MyStyle) {
    MyStyleDefault,
    MyStyleCustom
};

typedef NS_OPTIONS(NSInteger, MyOption) {
    MyOption1 = 1 << 0,
    MyOption2 = 1 << 1,
};
Run Code Online (Sandbox Code Playgroud)

得到了这个.

typedef enum MyStyle : NSInteger MyStyle; enum MyStyle : NSInteger {
    MyStyleDefault,
    MyStyleCustom
};

typedef enum MyOption : NSInteger MyOption; enum MyOption : NSInteger {
    MyOption1 = 1 << 0,
    MyOption2 = 1 << 1,
};
Run Code Online (Sandbox Code Playgroud)

我知道NS_OPTIONS用于位掩码,但是有任何技术差异吗?或者这仅仅是为了命名约定?

编辑

根据NS_OPTIONS的定义,它可能与编译器兼容.(特别是对于c ++编译器)

// In CFAvailability.h
// Enums and Options
#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum))
  #define CF_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
  #if (__cplusplus)
    #define CF_OPTIONS(_type, _name) _type _name; enum : _type
  #else
    #define CF_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
  #endif
#else
  #define CF_ENUM(_type, _name) _type _name; enum
  #define CF_OPTIONS(_type, _name) _type _name; enum
#endif
Run Code Online (Sandbox Code Playgroud)

clang中的__cplusplus值是199711,但我无法测试这究竟是什么.

ork*_*den 52

枚举和位掩码(选项)之间存在基本区别.您使用枚举列出独占状态.当多个属性可以同时应用时,将使用位掩码.

在这两种情况下,您都使用整数,但您会以不同的方式查看它们.使用枚举,您可以查看数值,使用位掩码查看各个位.

typedef NS_ENUM(NSInteger, MyStyle) {
    MyStyleDefault,
    MyStyleCustom
};
Run Code Online (Sandbox Code Playgroud)

只会代表两个州.您可以通过测试相等性来检查它.

switch (style){
    case MyStyleDefault:
        // int is 0
    break;
    case MyStyleCustom:
        // int is 1
    break;
}
Run Code Online (Sandbox Code Playgroud)

而位掩码将代表更多的状态.您可以使用逻辑或按位运算符检查各个位.

typedef NS_OPTIONS(NSInteger, MyOption) {
    MyOption1 = 1 << 0, // bits: 0001
    MyOption2 = 1 << 1, // bits: 0010
};

if (option & MyOption1){ // last bit is 1
    // bits are 0001 or 0011
}
if (option & MyOption2){ // second to last bit is 1
    // bits are 0010 or 0011
}
if ((option & MyOption1) && (option & MyOption2)){ // last two bits are 1
    // bits are 0011
}
Run Code Online (Sandbox Code Playgroud)

tl; dr枚举为数字命名.位掩码为位提供名称.

  • omg,你说得对!我错误地认为1 << 0是0.非常感谢你的澄清! (3认同)

Lan*_*nce 15

唯一的主要区别是使用适当的宏允许Code Sense(Xcode的代码完成)更好地进行类型检查和代码完成.例如,NS_OPTIONS允许编译器确保您|在一起的所有枚举具有相同的类型.

如需进一步阅读,请访问:http://nshipster.com/ns_enum-ns_options/

编辑:

现在Swift即将推出,强烈建议使用NS_ENUM/OPTIONS,以便枚举可以正确地桥接到快速枚举.

  • 我不认为_compiler_存在任何差异,特别是因为在预处理之后,不再有宏,并且_compiler_将在预处理_之后看到OP提供的相同代码.在参数完成方面,Xcode并不是很明智.在我看来,参数完成完全基于字符串匹配. (2认同)

Ben*_*n S 7

唯一的区别是让使用这些值的开发人员知道在OR'ed bitmask中使用它们是否有意义.

编译器不关心你使用哪一个:)

  • *"编译器并不关心你使用哪一个:)"* - 我想你可以说编译器不关心一点:P (3认同)