系统框架频繁用到C语言中的枚举类型,开发者常常容易忽略枚举的使用,苹果就多用 2的幂 来表示枚举类型。
-
用枚举来表示状态机的状态,传递给方法的选项以及状态码等值。
编译器会为枚举分配一个独特的符号,从0开始,每个枚举递增1。实现枚举所用的数据类型取决于编译器,不过其二进制位(一个字节含8个二进制位,所以至多可取2的八次方,即256种枚举)的个数必须能完全表示下枚举变好才行。
使用typedef关键字来定义枚举类型:
enum EOCConnetionState{
EOCConnetionStateDisconnected,
EOCConnetionStateConnecting,
EOCConnetionStateConnected,
};
typedef enum EOCConnectstate EOCConnectstate;
EOCConnectstate state = EOCConnetionStateDisconnected;
-
如果传递给某方法的选项为枚举类型,又可多个选项同时使用,就定义为 2的幂,通过 按位或 操作将其组合起来。
例如,iOS UI框架里就有如下枚举类型,表示某个视图应如何在水平或者垂直方向上调整大小:
enum UIViewAutoresizing{
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
......
}
用“按位或操作符”即可组合多个选项:
enum UIViewAutoresizing resizing = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight ;
if ( resizing & UIViewAutoresizingFlexibleWidth) {
// UIViewAutoresizingFlexibleWidth is set
}

系统库中就频繁使用这个方法。iOS UI框架中还有一个常用的例子,用枚举值告诉系统视图所支持的设备显示方向。开发者需实现一个名为supportedInterfaceOrientations的方法,将视图所支持的显示方向告诉系统:
- (NSUinteger) supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMasklandscapeLeft;
}
-
用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,
};
如果支持新特性,那么用NS_ENUM宏所定义的枚举类型展开之后就是:
typedef enum EOCConnectionState : NSUInteger EOCConnectionState;
enum EOCConnectionState : NSUInteger {
EOCConnectionStateDisconnected,
EOCConnectionStateConnecting,
EOCConnectionStateConnected,
};
根据是否要将代码按C++模式编译,NS_OPTIONS宏的定义方式也有所不同。如果不按c++编译,那么其展开方式就和NS ENUM相同。若按C ++编译,则展开后的代码略有不同。原因在于,用按位或运算来操作两个枚举值时,C++编译模式的处理办法与非 C++模式不一样。而上面已经提到了,作为选项的枚举值经常需要用按位或运算来组合。在用或运算操作两个枚举值时,C++认为运算结果的数据类型应该是枚举的底层数据类型,也就是NSUIntegero而且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,
};
若编译器按c++模式编译(也可能是按Objective-C++模式编译),则会给出下列错误信息:
error: cannot initialize a variable of type
'EOCPermittedDirection' with an rvalue of type 'int'
所以,在C++模式下应该用另一种方式定义NS_OPTIONS宏,以便省去类型转换操作。鉴于此,凡是需要以按位或操作来组合的枚举都应使用NS_OPTIONS 定义。若是枚举不需要互相组合,则应使用NS_ENUM来定义。
-
如果用switch处理枚举(要处理所有类型),不要实现default分支。
假如写上了default分支,稍后在枚举中加入了一个新状态,它(default)就会自动处理掉这个新状态,导致编译器不发出警告信息,不会提示开发者新加入的状态未在switch分支中处理。
网友评论