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被认为是NSInteger
types,但是MyEnumType1 | MyEnumType2
MyEnumType1 | MyEnumType2
的types是MyEnumType
,这个赋值不能在没有types转换的情况下执行, C ++禁止隐式types转换 。
在这个时候,我们需要NS_OPTIONS,在C ++ 11之前,NS_OPTIONS回退到枚举types,所以确实没有MyEnumType
, MyEnumType
只是NSInteger
另一个名字,
enum MyEnumType aVar = MyEnumType1 | MyEnumType2;
将编译,因为它是NSInteger
分配给NSInteger
。