首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Objective-C枚举、NS_ENUM和NS_OPTIONS

Objective-C枚举、NS_ENUM和NS_OPTIONS
EN

Stack Overflow用户
提问于 2012-12-29 18:24:25
回答 2查看 18.7K关注 0票数 22

在Objective-C中创建具有特定类型的枚举的正确方法是什么?NS_ENUM和NS_OPTIONS是如何工作的?像NSAutoresizing一样,NS_OPTIONS是用来做面具的吗?谢谢。

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

发布于 2012-12-29 20:08:03

来自NSHipster的示例。NS_OPTIONS以类似的方式使用,但用于通常是位掩码的枚举

而不是

代码语言:javascript
复制
typedef enum {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
} UITableViewCellStyle;

代码语言:javascript
复制
typedef enum {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};

typedef NSInteger UITableViewCellStyle;

执行以下操作:

代码语言:javascript
复制
typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};

NS_OPTIONS枚举示例:

代码语言:javascript
复制
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
};
票数 35
EN

Stack Overflow用户

发布于 2014-12-08 10:03:07

除了它们推断出不同类型的枚举之外,这两种方法之间存在差异。

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

这是原始代码:

代码语言: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-C导入了这个功能,但它带来了一个问题,当进行按位计算时,如下所示:

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

此代码不能在C++/Objective-C++编译中编译,因为aVar被认为是NSInteger类型,而MyEnumType1 | MyEnumType2MyEnumType类型,如果没有类型转换,此赋值将无法执行,C++禁止隐式类型转换

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

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

将编译,因为它将NSInteger赋值给NSInteger

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14080750

复制
相关文章

相似问题

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