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来定义。
时间: 2024-11-10 07:08:24