概述
在C、C++、Java这些语言中就有它们对应的枚举,定义的方式也多种多样,但使用目的只有一个:让代码可读性更强。这里我们只简单说说Objective-C中枚举的使用。
在Apple提供给我们的API中,经常会看到使用枚举的例子:
有这样的:
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
};
还有这样的:
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
可以看到在Objective-C中为我们提供了两种定义宏的枚举:NS_ENUM 和 NS_OPTIONS,这两者其实本质上是一样的,都是用来声明枚举的,不过细小的区别还是有的。
NS_ENUM:常用来声明一般的NSInteger类型的枚举。
NS_OPTIONS:常用来声明NSUinteger类型的明位掩码(bitmasked)。
说明:用enum就可以声明一般类型和位掩码类型,但是苹果官方建议我们使用NS_ENUM 和 NS_OPTIONS,它们可以推断出不同类型的枚举,还可以适配到不同的开发平台。
NS_OPTIONS
我们重点看看NS_OPTIONS类型的枚举:
在NS_OPTIONS类型的枚举中,我们看到每个枚举值后有“ <<”,其实这就是左移位运算符,这样我们就可以通过“|”(或位运算符)进行组合使用,a << b就表示把a转化为二进制后左移b位。
使用场景:如果一个枚举变量可能代表多个枚举值的时候,我们就需要声明成NS_OPTIONS类型的枚举。其原理只是把各个枚举值加起来(转化成十进制再想加),获得一个新值(十进制)。我们知道枚举值相对唯一,位运算就很好的解决了这个问题,它可以确保枚举值组合在一起的唯一性。
那么苹果官方是怎么知道我们多个条件组合使用了呢?答案是通过&(与位运算符)进行判断的:
NSUInteger controlEvents = UIControlEventEditingDidBegin | UIControlEventValueChanged | UIControlEventEditingDidEnd;
if (controlEvents & UIControlEventEditingDidBegin) {
NSLog(@"UIControlEventEditingDidBegin");
} else if (controlEvents & UIControlEventValueChanged) {
NSLog(@"UIControlEventValueChanged");
} else if (controlEvents & UIControlEventEditingDidEnd) {
NSLog(@"UIControlEventEditingDidEnd");
}
在这里我举例说明NS_OPTIONS类型枚举的用法:
typedef NS_OPTIONS(NSUInteger, MyType) {
MyTypeA = 1 << 0, //值为1,2的0次方
MyTypeB = 1 << 1, //值为2,2的1次方
MyTypeC = 1 << 2, //值为4,2的2次方
MyTypeD = 1 << 3, //值为8,2的3次方
};
NSUInteger value = MyTypeA | MyTypeB;
NSLog(@"%zd, %zd, %zd, %zd", value & MyTypeA, value & MyTypeB, value & MyTypeC, value & MyTypeD);
// 输出结果:1, 2, 0, 0
这里我们再通过二进制解释一下:
转化成二进制:
MyTypeA: 0 0 0 1
|
MyTypeB: 0 0 1 0
|
MyTypeC: 0 1 0 0
|
MyTypeD: 1 0 0 0
----------------
value : 1 1 1 1
ps:以上的结果是通过|得到value的值(|的意思是只要有一个为1,结果就为1)
value : 1 1 1 1
&
MyTypeA: 0 0 0 1
----------------
结果值: 0 0 0 1
ps:0001就是MyTypeA的值
从结果可以看出:1是MyTypeA的值,2是MyTypeB的值,其它枚举值没有参与组合使用,值都为0。这也说明,如果value & MyTypeC的值为0,说明value不包含MyTypeC,反之亦然。