NS_ENUM和NS_OPTIONS有什么区别?

我在Xcode5中预处理了以下代码。

typedef NS_ENUM(NSInteger, MyStyle) { MyStyleDefault, MyStyleCustom }; typedef NS_OPTIONS(NSInteger, MyOption) { MyOption1 = 1 << 0, MyOption2 = 1 << 1, }; 

得到这个。

 typedef enum MyStyle : NSInteger MyStyle; enum MyStyle : NSInteger { MyStyleDefault, MyStyleCustom }; typedef enum MyOption : NSInteger MyOption; enum MyOption : NSInteger { MyOption1 = 1 << 0, MyOption2 = 1 << 1, }; 

我知道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 

叮当中的__cplusplus值是199711,我无法testing这是什么,但是。

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

在这两种情况下,你使用整数,但你看着他们不同。 用enum来看看数值,用位掩码来看个别位。

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

只会代表两个国家。 你可以简单地通过testing平等来检查它。

 switch (style){ case MyStyleDefault: // int is 0 break; case MyStyleCustom: // int is 1 break; } 

位掩码将代表更多的状态。 用逻辑或按位运算符检查各个位。

 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 } 

tl;博士 enum给名字给数字。 一个位掩码给位的名字。

唯一的区别是使用适当的macros允许Code Sense(Xcode的代码完成)更好地进行types检查和代码完成。 例如,NS_OPTIONS允许编译器确保所有的枚举你 一起是相同的types。

有关进一步阅读,请参阅: http : //nshipster.com/ns_enum-ns_options/

编辑:

现在,Swift即将到来,强烈build议使用NS_ENUM / OPTIONS,以便enum可以正确桥接到一个快速枚举。

唯一的区别是让开发人员使用这些值是否知道在OR'ed位掩码中使用它们是否合理。

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

我从这个问题复制我的答案Objective-C枚举,NS_ENUM和NS_OPTIONS :

由于添加该问题的用户很长一段时间没有活动,所以也许你可以为在这里search和查找的人提供我的答案。

下面是答案

除了他们推断不同种类的枚举之外,两者之间是有区别的。

在Objective-C ++模式下编译时,它们生成不同的代码:

这是原来的代码:

 typedef NS_OPTIONS(NSUInteger, MyOptionType) { MyOptionType1 = 1 << 0, MyOptionType2 = 1 << 1, }; typedef NS_ENUM(NSUInteger, MyEnumType) { MyEnumType1 = 1 << 0, MyEnumType2 = 1 << 1, }; 

这是macros在Objective-C编译时扩展的代码:

 typedef enum MyOptionType : NSUInteger MyOptionType; enum MyOptionType : NSUInteger { MyOptionType1 = 1 << 0, MyOptionType2 = 1 << 1, }; typedef enum MyEnumType : NSUInteger MyEnumType; enum MyEnumType : NSUInteger { MyEnumType1 = 1 << 0, MyEnumType2 = 1 << 1, }; 

这是macros在Objective-C++编译中扩展时的代码:

 typedef NSUInteger MyOptionType; enum : NSUInteger { MyOptionType1 = 1 << 0, MyOptionType2 = 1 << 1, }; typedef enum MyEnumType : NSUInteger MyEnumType; enum MyEnumType : NSUInteger { MyEnumType1 = 1 << 0, MyEnumType2 = 1 << 1, }; 

看到两种模式之间的NS_OPTIONS的区别?

HERE IS THE REASON

在C ++ 11中有一个新特性,你可以为枚举声明一个types,在此之前,枚举types由编译器根据枚举的最大值决定。

因此,在C ++ 11中,由于您可以自己决定枚举的大小,因此可以转发declare枚举而不用实际定义它们,如下所示:

 //forward declare MyEnumType enum MyEnumType: NSInteger //use myEnumType enum MyEnumType aVar; //actually define MyEnumType somewhere else enum MyEnumType: NSInteger { MyEnumType1 = 1 << 1, MyEnumType2 = 1 << 2, } 

这个特性非常方便,Objective-C引入了这个特性,但是在按位计算时会带来一个问题,就像这样:

 enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 

此代码无法在C ++ / Objective-C ++编译中编译,因为aVar被认为是NSIntegertypes,但是MyEnumType1 | MyEnumType2 MyEnumType1 | MyEnumType2的types是MyEnumType ,这个赋值不能在没有types转换的情况下执行, C ++禁止隐式types转换

在这个时候,我们需要NS_OPTIONS,在C ++ 11之前,NS_OPTIONS回退到枚举types,所以确实没有MyEnumTypeMyEnumType只是NSInteger另一个名字,

 enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 

将编译,因为它是NSInteger分配给NSInteger