首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >NS_ENUM和NS_OPTIONS有什么区别?

NS_ENUM和NS_OPTIONS有什么区别?
EN

Stack Overflow用户
提问于 2013-09-23 15:17:23
回答 4查看 22.2K关注 0票数 32

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

代码语言:javascript
运行
复制
typedef NS_ENUM(NSInteger, MyStyle) {
    MyStyleDefault,
    MyStyleCustom
};

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

还有这个。

代码语言:javascript
运行
复制
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++编译器)。

代码语言:javascript
运行
复制
// 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,我无法测试这到底是为了什么。

EN

Stack Overflow用户

发布于 2014-12-08 02:10:14

我抄袭了OPTIONS这个问题的答案

因为添加这个问题的用户已经很长时间没有活跃起来了,也许您可以为在这里搜索和找到的人提供我的答案。

下面的答案是复制的

这两种不同之处在于,它们推断出不同种类的枚举。

当以Objective++模式编译时,它们生成不同的代码:

这是原始代码:

代码语言:javascript
运行
复制
typedef NS_OPTIONS(NSUInteger, MyOptionType) {
    MyOptionType1 = 1 << 0,
    MyOptionType2 = 1 << 1,
};

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

这是在Objective-C编译中展开宏时的代码:

代码语言:javascript
运行
复制
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++编译中展开宏时的代码:

代码语言:javascript
运行
复制
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中,由于您可以自己决定枚举的大小,所以可以转发声明枚举,而无需实际定义枚举,如下所示:

代码语言:javascript
运行
复制
//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导入了这个特性,但是当按位计算时,它会带来一个问题,如下所示:

代码语言:javascript
运行
复制
enum MyEnumType aVar = MyEnumType1 | MyEnumType2;

这段代码不能在C++/Objective++编译中编译,因为aVar被认为是NSInteger类型,而MyEnumType1 | MyEnumType2是类型MyEnumType,因此没有类型强制转换就无法执行此赋值,C++禁止隐式类型强制转换

此时,我们需要NS_OPTIONS,NS_OPTIONS回到C++ 11之前的枚举,这样就没有MyEnumType --实际上,MyEnumType只是NSInteger的另一个名称,所以代码类似

代码语言:javascript
运行
复制
enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 

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

票数 1
EN
查看全部 4 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18962925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档