第五条:用枚举表示状态、选项、状态码
- 在以一系列常量来表示状态码或可组合的选项的时候,可以使用枚举命名。使用枚举可以增加代码的可读性。比如使用枚举表示网络连接状态:
enum EOCConnectionState {
EOCConnectionStateDisconnected,
EOCConnectionStateConnecting,
EOCConnectionStateConnected,
};
-
编译器会为枚举分配一个独有的编号,从0开始,每个枚举递增1。
-
如下,定义一个枚举变量的写法不是很简洁
enum EOCConnectionState state = EOCConnectionStateDisconnected;
- 由于定义枚举变量写法不是很简洁,可以使用
typedef
关键字简化一下。
typedef enum EOCConnectionState EOCConnectionState;
EOCConnectionState state = EOCConnectionStateDisconnected;
- 可以为枚举指定数据类型,并且设置枚举选项的值,其他选项自动递增1
enum EOCConnectionState: NSInteger {
EOCConnectionStateDisconnected = 1,
EOCConnectionStateConnecting,
EOCConnectionStateConnected,
};
- 定义选项,并且这些选项还可以彼此组合的时候,应该使用枚举类型。各个选项之间可以通过按位或操作进行组合。在iOS中,UIKit框架有很多这种组合。
enum UIViewAutoresizing {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0, // 1左移0位
UIViewAutoresizingFlexibleWidth = 1 << 1, // 1左移1位
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
他们的二进制分别如下表示:
UIViewAutoresizingNone 0 0 0 0 0 0 0
UIViewAutoresizingFlexibleLeftMargin 0 0 0 0 0 0 1
UIViewAutoresizingFlexibleWidth 0 0 0 0 0 1 0
UIViewAutoresizingFlexibleRightMargin 0 0 0 0 1 0 0
UIViewAutoresizingFlexibleTopMargin 0 0 0 1 0 0 0
UIViewAutoresizingFlexibleHeight 0 0 1 0 0 0 0
UIViewAutoresizingFlexibleBottomMargin 0 1 0 0 0 0 0
按位或:按位或的2位二进制,如果其中1位为1那么结果为1。
以UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight 举例来说。
0 0 0 0 0 1 0
0 0 1 0 0 0 0
------------------ 按位或
0 0 1 0 0 1 0
我们如何知道怎么组合的呢?就用到了按位与(&)操作:按位与的2位二进制,如果都为1,那么结果为1,否则为0
我们拿到枚举选项的二进制&按位或的结果,就可以得出使用的哪个选项
0 0 1 0 0 1 0 result
0 0 0 0 0 1 0 UIViewAutoresizingFlexibleWidth
------------------ 按位与
0 0 0 0 0 1 0 ->>> UIViewAutoresizingFlexibleWidth
0 0 1 0 0 1 0
0 0 1 0 0 0 0
------------------ 按位与
0 0 1 0 0 0 0 ->>> UIViewAutoresizingFlexibleHeight
具体到代码的判断:
enum UIViewAutoresizing result = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
if (result & UIViewAutoresizingFlexibleWidth) {
// 使用了UIViewAutoresizingFlexibleWidth
}
if (result & UIViewAutoresizingFlexibleHeight) {
// 使用了UIViewAutoresizingFlexibleHeight
}
如果result & 其他选项的二进制,结果就是0,不会进入if判断。
- Foundation框架中定义一些辅助的宏,也可以指定保存枚举值的数据类型。这些宏具备向后兼容的能力,如果目标平台的编译器支持新标准,就使用新式语法,否则使用旧式语法。
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
};
- 我们总习惯使用
switch
语句加上default
分支处理枚举选项。如果使用枚举来定义状态,建议不要使用default
分支。因为在缺少某一项枚举状态或新增一个状态的时候,编译器会发出警告。如果加了default
分支,很漏掉其中一个选项。
网友评论