C 与 Objective-C 中的枚举
本文介绍 C 与 Objective-C 中的枚举,同时对 Objective-C 中的字符串枚举进行介绍
C语言中的枚举
C语言中也是有枚举的,或者说枚举正是从C语言中诞生的。在C语言中,枚举使用 enum
关键字声明,辅以 typedef
。让我们来举个例子:
typedef enum RKOEnumType {
RKOEnumTypeNone = 0,
RKOEnumTypeNormal,
...
} RKOEnumType;
上面的代码便定义了一个枚举类型 RKOEnumType
,使用它声明变量时我们可以这么使用:
RKOEnumType type = RKOEnumTypeNone;
而用它进行判断时则是这样的:
switch (type) {
case RKOEnumTypeNone:
// some code
break;
case RKOEnumTypeNormal:
// some code
break;
...
}
Objective-C 中的枚举
在 Objective-C
语言中,Foundaation
框架为我们封装了一套更方便的枚举定义方法。那便是 NS_ENUM
和 NS_OPTIONS
。
NS_ENUM
NS_ENUM
用来申明单选类型的枚举,即枚举变量中只可以有一种值。让我们来看一下栗子:
typedef NS_ENUM(NSInteger, RKOEnumType) {
RKOEnumTypeNone = 0,
RKOEnumTypeNormal,
...
};
我们可以看到,这里用 NSInteger
声明了枚举变量的类型,即整数类型,其在使用时和 C语言
并无区别,依然使用 switch
语法用以区分每种不同的枚举变量。
NS_OPTIONS
除了 NS_ENUM
之后,Objective-C
还为我们封装了一套 NS_OPTIONS
。有的时候单一的枚举值并不满足我们的需求,例如在如下场景时:我们希望设一个视图的可选转方向,它即可向左旋转,又可向右旋转。这时如果我们使用枚举来代表旋转方向的话,显然我们不应该设置一个枚举值为“既可向左又可向右”,我们依然定义一个 RKORotatTypeLeft
一个 RKORotatTypeRight
,然后多选它们。那么我们该如何定义呢?下面来举个例子:
typedef NS_OPTIONS(NSUInteger, RKORotatType) {
RKORotatTypeRightNone = 0, // 2进制中的 0000
RKORotatTypeRight = 1 << 0, // 值为2的0次方,二进制中的 0001
RKORotatTypeLeft = 1 << 1, // 值为2的1次方,二进制中的 0010
...
};
这样我们使用 NS_OPTIONS
,结合位移操作,就定义了一个可以进行多选的枚举类型了。需要注意的是,NS_OPTIONS
使用的变量类型为 NSUInteger
。而不是 NS_ENUM
的 NSInteger
。
在对变量赋值时,我们使用 |
或运算符连接多个不同的枚举值,例如:
RKORotatType type = RKORotatTypeRight | RKORotatTypeLeft;
判断
NS_OPTIONS
在对变量的判断上与 NS_ENUM
不同,因为变量中可以包含多个值,所以我们就不方便使用 switch
来进行判断了。
一般的,我们使用 if
来进行 NS_OPTIONS
类型的枚举的值判读,如下所示:
// RKORotatTypeRight
if (type & RKORotatTypeRight) {
// some code
}
// 包含 RKORotatTypeLeft
if (type & RKORotatTypeLeft) {
// some code
}
使用 if
判断,结合 &
与运算符,我们即可判断变量中是否包含某个具体的枚举值,进而执行操作。
排除
有的时候,我们为了方便,有可能定义下面这样的一个选项枚举:
typedef NS_OPTIONS(NSUInteger, RKORotatType) {
RKORotatTypeRightNone = 0,
RKORotatTypeRight = 1 << 0,
RKORotatTypeLeft = 1 << 1,
RKORotatTypeTop = 1 << 2,
RKORotatTypeBottom = 1 << 3,
RKORotatTypeAll = RKORotatTypeRight | RKORotatTypeLeft | RKORotatTypeTop | RKORotatTypeBottom,
};
这里我额外定义了一个枚举选项为 RKORotatTypeAll
,代表所有的旋转类型。现在我们有可能有这么一个需求,点击某个按钮,或者执行了某个操作之后,要禁止这个视图向左旋转。
我们可以重新对 type
进行赋值,也可以像下面这样,将 RKORotatTypeLeft
从 type
中排除掉:
type = type & (~RKORotatTypeLeft);
将 RKORotatTypeLeft
取反后再与 type
进行与操作,即可从 type
中移除 RKORotatTypeLeft
选项。
C数组与字符串枚举
如上所述,c 与 Objective-C 的常见枚举都是 int
类型,如果我们需要一个字符串枚举呢?
我们可以借助 c 数组来实现。首先定义一个常见的 Objective-C 枚举:
typedef NS_ENUM(NSUInteger, KLType) {
KLTypeRed = 1,
KLTypeGreen = 2,
KLTypeOrange = 3,
};
随后使用该 Objective-C 枚举作为下标,定义 c 数组:
// 这个是 Map NSString * 类型的数组
NSString *KLTypeStringMap[] = {
[KLTypeRed] = @"红色",
[KLTypeGreen] = @"绿色",
[KLTypeOrange] = @"橘色"
};
// 使用:
KLTypeStringMap[KLTypeRed];