NS_ENUM和NS_OPTIONS有什么区别?

时间:2013-09-23 15:17:23

标签: ios objective-c cocoa

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

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
clang中的

__ cplusplus值是199711,我无法测试这究竟是什么。

4 个答案:

答案 0 :(得分:51)

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

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

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

仅代表两个州。您可以通过测试相等性来检查它。

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; dr 枚举为数字指定名称。位掩码为位提供名称。

答案 1 :(得分:15)

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

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

编辑:

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

答案 2 :(得分:7)

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

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

答案 3 :(得分:1)

我从这个问题复制了我的答案Objective-C Enumeration, NS_ENUM & NS_OPTIONS

由于添加该问题的用户长时间没有活动,也许您可​​以为搜索和查找此处的用户推荐我的答案。

以下是答复的答案

除了他们推断出不同类型的枚举之外,两者之间存在差异。

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

这是原始代码:

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

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

这是在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,
};

这是在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中有一个新功能,你可以为枚举声明一个类型,在此之前,类型持有枚举由编译器根据枚举的最大值决定。

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

//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类型但MyEnumType1 | MyEnumType2属于MyEnumType类型,此分配可以&#39 ; t没有类型转换, C ++禁止隐式类型转换

目前,我们需要NS_OPTIONS,NS_OPTIONS回退到C ++ 11之前的枚举,因此确实没有MyEnumTypeMyEnumType只是NSInteger的另一个名称,所以像

这样的代码
enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 

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

相关问题