美文网首页
iOS 用枚举来表示状态机、状态码

iOS 用枚举来表示状态机、状态码

作者: Yimmm | 来源:发表于2021-02-28 23:46 被阅读0次

系统框架频繁用到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分支中处理。

相关文章

网友评论

      本文标题:iOS 用枚举来表示状态机、状态码

      本文链接:https://www.haomeiwen.com/subject/seomfltx.html