在写代码的过程中我们会经常定义enum类型,这样做的好处是用enum关键字说明的常量由编译程序自动生成,我们不需要用手工对常量一一赋值,也增强了程序的可读性。但在OC中,苹果封装了这两个宏:NS_ENUM、NS_OPTIONS,又有什么区别呢?下面就一起试一下。
1、C语言类型的enum定义方式:
typedef enum : NSUInteger {
name1 = 0,
name2,
name3,
name4,
} NameType;
@interface Person : NSObject
@property(nonatomic,assign)NameType nameType;
@end
Person *person1 = [[Person alloc] init];
person1.nameType = name3;
if (person1.nameType & (name2 | name3)) {
NSLog(@"nametype为2或3");
}
if (person1.nameType & (name3 | name4)) {
NSLog(@"nametype为3或4");
}
输出结果为:
2017-03-06 18:33:36.247 TestProiect[72241:6511639] nametype为2或3
2017-03-06 18:33:36.247 TestProiect[72241:6511639] nametype为3或4
2、NS_ENUM定义方式:
typedef NS_ENUM(NSInteger,NameType){
name1 = 0,
name2,
name3,
name4,
};
输出结果为:
2017-03-06 18:39:03.505 TestProiect[72261:6516433] nametype为2或3
2017-03-06 18:39:03.506 TestProiect[72261:6516433] nametype为3或4
3、NS_OPTIONS定义方式,定义位掩码(Bitmask):
typedef NS_OPTIONS(NSInteger,NameType){
name1 = 0,
name2 = 1 << 0,
name3 = 1 << 1,
name4 = 1 << 2,
};
输出结果为:
2017-03-06 18:41:00.804 TestProiect[72281:6518961] nametype为2或3
2017-03-06 18:41:00.804 TestProiect[72281:6518961] nametype为3或4
这样看起来这三种定义枚举类型的方式结果基本相同,那它们的区别是什么呢?
首先,enum是C语言方式的定义,在OC中苹果推荐我们尽量使用后两种方法来定义枚举。
关于NS_ENUM与NS_OPTIONS,我在stackOverflow上找到了这样的回答:What is the difference between NS_ENUM and NS_OPTIONS?
里面的最多赞同答案解释的很详细,首先:
There's a basic difference between an enum and a bitmask (option). You use an enum to list exclusive states. A bitmask is used when several properties can apply at the same time.
翻译过来就是:关于NS_ENUM与NS_OPTIONS的使用方式,一个最基本的原则:如果列举的类型之间是一种互斥的关系,那么用NS_ENUM;如果列举的类型之间没有明显的互斥关系,即一个枚举变量可能要同时代表多个枚举值,那么就用NS_OPTIONS
所以,我们在区别使用NS_ENUM定义的类型时可以使用switch语法,这样:
typedef NS_ENUM(NSInteger, MyStyle) {
MyStyleDefault,
MyStyleCustom
};
switch (style){
case MyStyleDefault:
// int is 0
break;
case MyStyleCustom:
// int is 1
break;
}
在区别使用NS_OPTIONS定义的类型时,因为NS_OPTIONS基于位掩码的声明,可以这样:
typedef NS_OPTIONS(NSInteger, MyOption) {
MyOption1 = 1 << 0, // bits: 0001
MyOption2 = 1 << 1, // bits: 0010
};
if (option & MyOption1){ // last bit is 1
// bits are 0001 or 0011
}
if (option & MyOption2){ // second to last bit is 1
// bits are 0010 or 0011
}
if ((option & MyOption1) && (option & MyOption2)){ // last two bits are 1
// bits are 0011
}
最后可以用一句话概括:
An enum gives names to numbers. A bitmask gives names to bits.
即一般来说NS_ENUM枚举的元素是整型,NS_OPTIONS枚举的元素是位掩码。
对于位掩码不了解的同学可以看下这里:iOS 枚举的巧用
PS:之所以加一个一般来说,是因为其实两者基本思想是没有区别的,据其根本,枚举的目的是为整型数据添加一个名字。NS_ENUM,NS_OPTIONS只是为了代码的统一性,约束一下编码规则罢了。
参考资料:
What is the difference between NS_ENUM and NS_OPTIONS?