NS_ENUM vs. NS_OPTIONS

Posted Gabriel_Lee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NS_ENUM vs. NS_OPTIONS相关的知识,希望对你有一定的参考价值。

NS_ENUM用于定义普通枚举值,NS_OPTIONS用于定义位移相关操作的枚举值:

typedef NS_ENUM(NSUInteger, EOCConnectionState) {  
    EOCConnectionStateDisconnected,  
    EOCConnectionStateConnecting,  
    EOCConnectionStateConnected,  
};  

typedef NS_OPTIONS(NSUInteger, EOCPermittedDirection) {  
    EOCPermittedDirectionUp    = 1 << 0,  
    EOCPermittedDirectionDown  = 1 << 1,  
    EOCPermittedDirectionLeft  = 1 << 2,  
    EOCPermittedDirectionRight = 1 << 3,  
}; 

根据是否要将代码按C++模式编译,NS_OPTIONS宏的定义方式有所不同。如果不按C++编译,那么其展开方式就和NS_ENUM相同。若按C++编译,则展开后的代码略有不同。原因在于,用按位或运算来操作两个枚举值时,C++编译模式的处理办法与非C++模式不一样。作为选项的枚举值经常需要用按位或运算来组合,在用或运算操作两个枚举值时,C++认为运算结果的数据类型应该是枚举的底层数据类型,也就是NSUInteger,而且C++不允许将这个底层类型“隐式转换”(implicit cast)为枚举类型本身。

我们用EOCPermittedDirection来演示一下,假设按NS_ENUM方式将其展开:

typedef enum EOCPermittedDirection : int EOCPermittedDirection;  
enum EOCPermittedDirection : int {  
    EOCPermittedDirectionUp    = 1 << 0,  
    EOCPermittedDirectionDown  = 1 << 1,  
    EOCPermittedDirectionLeft  = 1 << 2,  
    EOCPermittedDirectionRight = 1 << 3,  
}; 

然后考虑下列代码:

OCPermittedDirection permittedDirections =  
    EOCPermittedDirectionLeft | EOCPermittedDirectionUp;

若编译器按C++模式编译(也可能是按Objective-C++模式编译),则会给出下列错误信息:

error: cannot initialize a variable of type  
EOCPermittedDirection with an rvalue of type int 

如果想编译这行代码,就要将按位或操作的结果显式转换(explicit cast)为EOCPermittedDirection。所以,在C++模式下应该用另一种方式定义NS_OPTIONS宏,以便省去类型转换操作。鉴于此,凡是需要以按位或操作来组合的枚举都应使用NS_OPTIONS定义。若是枚举不需要互相组合,则应使用NS_ENUM来定义。

以上是关于NS_ENUM vs. NS_OPTIONS的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 枚举类型 enum,NS_ENUM,NS_OPTIONS

枚举宏(Adopting Modern Objective-C)

可互操作的 Obj-C typedef NS_ENUM 到 swift

可互操作的 Obj-C typedef NS_ENUM 到 swift

NS_ENUM 对象在桥接头文件中添加后无法编译

怎么把unity代码嵌入vs2022