两者之间存在差异,只是它们推断出不同类型的枚举。
在 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 被认为是 typeNSInteger
但MyEnumType1 | MyEnumType2
属于 type ,如果没有类型转换MyEnumType
,此赋值无法执行,C++ 禁止隐式类型转换。
这时候,我们需要NS_OPTIONS,NS_OPTIONS回退到C++ 11之前的enum,这样MyEnumType
确实没有,MyEnumType
只是另外一个名字NSInteger
,这样代码就好了
enum MyEnumType aVar = MyEnumType1 | MyEnumType2;
将编译,因为它分配NSInteger
给NSInteger
.