Objective-C Enumeration, NS_ENUM & NS_OPTIONS
在Objective-C中创建具有特定类型的枚举的正确方法是什么?ns-enum和ns-u选项如何工作?ns选项用于遮罩,如nsautoresizing?谢谢。
1 2 3 | Code from NSObjCRuntime.h #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type #define NS_OPTIONS(_type, _name) _type _name; enum : _type |
NShipster的示例。ns_选项以类似的方式使用,但对于通常是位掩码的枚举
而不是
1 2 3 4 5 6 | typedef enum { UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2, UITableViewCellStyleSubtitle } UITableViewCellStyle; |
或
1 2 3 4 5 6 7 8 | typedef enum { UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2, UITableViewCellStyleSubtitle }; typedef NSInteger UITableViewCellStyle; |
这样做:
1 2 3 4 5 6 | typedef NS_ENUM(NSInteger, UITableViewCellStyle) { UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2, UITableViewCellStyleSubtitle }; |
示例ns_options枚举:
1 2 3 4 5 6 7 8 9 | typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { UIViewAutoresizingNone = 0, UIViewAutoresizingFlexibleLeftMargin = 1 << 0, UIViewAutoresizingFlexibleWidth = 1 << 1, UIViewAutoresizingFlexibleRightMargin = 1 << 2, UIViewAutoresizingFlexibleTopMargin = 1 << 3, UIViewAutoresizingFlexibleHeight = 1 << 4, UIViewAutoresizingFlexibleBottomMargin = 1 << 5 }; |
这两者之间有区别,只是他们推断出不同的枚举类型。
在Objective-C++模式下编译时,它们会生成不同的代码:
这是原始代码:
1 2 3 4 5 6 7 8 9 | typedef NS_OPTIONS(NSUInteger, MyOptionType) { MyOptionType1 = 1 << 0, MyOptionType2 = 1 << 1, }; typedef NS_ENUM(NSUInteger, MyEnumType) { MyEnumType1 = 1 << 0, MyEnumType2 = 1 << 1, }; |
这是在
1 2 3 4 5 6 7 8 9 | 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, }; |
这是在
1 2 3 4 5 6 7 8 9 | 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_选项的区别了吗?
在C++ 11中有一个新特性,可以为枚举声明一个类型,在此之前,根据枚举的最大值由编译器决定类型保持枚举。
因此,在C++ 11中,由于可以自行决定枚举的大小,所以可以在不实际定义它们的情况下向前声明枚举,例如:
1 2 3 4 5 6 7 8 9 10 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导入了这个特性,但是在进行逐位计算时,它带来了一个问题,如下所示:
1 | enum MyEnumType aVar = MyEnumType1 | MyEnumType2; |
该代码不能在C++/Objule+C++编译中编译,因为AVAR被认为是EDCOX1的类型3,而EDCOX1×4是EDCOX1×5的类型,这个分配不能在没有类型转换的情况下执行,C++禁止隐式类型的转换。
此时,我们需要NSUPTIONS,NSLY选项在C++ 11之前回落到EnUM,因此没有EDOCX1 OR 5。确实,EDCOX1 OR 5是另一个EDCOX1(3)的名称,因此代码类似
1 | enum MyEnumType aVar = MyEnumType1 | MyEnumType2; |
将编译,因为它将