C列举,NS
在Objective-C中创建具有特定类型的枚举的正确方法是什么? NS_ENUM和NS_OPTIONS如何工作? NS_OPTIONS用于掩码,比如NSAutoresizing? 谢谢。
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_OPTIONS以类似的方式使用,但对于通常是位掩码的枚举
代替
typedef enum {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
} UITableViewCellStyle;
要么
typedef enum {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
};
typedef NSInteger UITableViewCellStyle;
做这个:
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
UITableViewCellStyleDefault,
UITableViewCellStyleValue1,
UITableViewCellStyleValue2,
UITableViewCellStyleSubtitle
};
一个例子NS_OPTIONS枚举:
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 ++模式下编译时,它们会生成不同的代码:
这是原始代码:
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中,由于您可以自己决定枚举的大小,因此您可以转发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
类型,但MyEnumType1 | MyEnumType2
MyEnumType1 | MyEnumType2
是类型的MyEnumType
,此分配不能没有一个类型转换执行,C ++禁止隐式类型铸造 。
此时,我们需要NS_OPTIONS,NS_OPTIONS在C ++ 11之前回退到enum,所以确实没有MyEnumType
, MyEnumType
只是NSInteger
另一个名称,所以代码就像
enum MyEnumType aVar = MyEnumType1 | MyEnumType2;
将编译,因为它将NSInteger
分配给NSInteger
。
上一篇: C Enumeration, NS