前言
Enumeration,enum,在程序设计语言中,一般用一个数值来代表某一状态,这种处理方法不直观,易读性差。如果能在程序中用自然语言中有相应含义的单词来代表某一状态,则程序就很容易阅读和理解。也就是说,事先考虑到某一变量可能取的值,尽量用自然语言中含义清楚的单词来表示它的每一个值,这种方法称为枚举方法,用这种方法定义的类型称枚举类型。
命名
定义的枚举类型名称通常与项目的类文件前缀相同,或者是类库框架缩写,或者跟随具体业务名,如果开头是缩写要大写表示,跟随其后的命名应采用驼峰命名法则,命名应准确表述枚举表示的意义,枚举中各个值都应以定义的枚举类型开头,其后跟随各个枚举值对应的状态、选项或者状态码
状态与选项(states and options)
状态
同时只能有一种,如“RecordPause”,“RecordEnd”,不可能同时Record是Pause和RecordEnd。如下
1 2 3 4 5 6 |
typedef NS_ENUM(NSUInteger, VoiceRecordStatus) { VoiceRecordStatusPrepare = 0, VoiceRecordStatusIng, VoiceRecordStatusPause, VoiceRecordStatusEnd }; |
由于每种状态都用一个便于理解的值来表示,所以这样写出来的代码更易读懂。编译器会为枚举分配一个独有的编号,从0开始,每个枚举递增1
选项
定义选项的时候。若这些选项可以彼此组合,则更应如此。只要枚举定义得对,各选项之间就可通过“按位或操作符”(bitwise OR operator)来组合。例如,iOS UI框架中有如下枚举类型,用来表示某个视图应该如何在水平或垂直方向上调整大小
位移枚举(可复选的枚举) 使用位移实现选项变量
本文使用 Autoresizing 的系统枚举UIViewAutoresizing作为基础进行讲述
以下位移已经计算提前计算出来了二进制与十进制值为了方便下文使用
1 2 3 4 5 6 7 8 9 |
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) { 二进制值 十进制 UIViewAutoresizingNone = 0, 0000 0000 0 UIViewAutoresizingFlexibleLeftMargin = 1 << 0, 0000 0001 1 UIViewAutoresizingFlexibleWidth = 1 << 1, 0000 0010 2 UIViewAutoresizingFlexibleRightMargin = 1 << 2, 0000 0100 4 UIViewAutoresizingFlexibleTopMargin = 1 << 3, 0000 1000 8 UIViewAutoresizingFlexibleHeight = 1 << 4, 0001 0000 16 UIViewAutoresizingFlexibleBottomMargin = 1 << 5 0010 0000 32 }; |
使用枚举定义选项,每个选项均可启用或禁用,使用上述方式来定义枚举值,每个枚举值所对应的二进制表示中,只有1个二进制位的值是1。用“按位或操作符”可组合多个选项
用 | 来隔开
1 |
aView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin |UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin; |
而且每一个枚举对应的逻辑都会覆盖到
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
-(void)todo:(UIViewAutoresizing)type{ if (type==0) { NSLog(@"UIViewAutoresizingNone"); return; } if (type & UIViewAutoresizingFlexibleLeftMargin) { NSLog(@"UIViewAutoresizingFlexibleLeftMargin"); } if (type & UIViewAutoresizingFlexibleWidth) { NSLog(@"UIViewAutoresizingFlexibleWidth"); } if (type & UIViewAutoresizingFlexibleRightMargin) { NSLog(@"UIViewAutoresizingFlexibleRightMargin"); } if (type & UIViewAutoresizingFlexibleTopMargin) { NSLog(@"UIViewAutoresizingFlexibleTopMargin"); } if (type & UIViewAutoresizingFlexibleHeight) { NSLog(@"UIViewAutoresizingFlexibleHeight"); } if (type & UIViewAutoresizingFlexibleBottomMargin) { NSLog(@"UIViewAutoresizingFlexibleBottomMargin"); } } |
1 2 3 4 5 |
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. [self todo:UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleHeight]; } |
结果输出
UIViewAutoresizingFlexibleLeftMargin
UIViewAutoresizingFlexibleRightMargin
UIViewAutoresizingFlexibleHeight
二进制转十进制
1101(2)=1*2^0+0*2^1+1*2^2+1*2^3=1+0+4+8=13转化成十进制要从右到左用二进制的每个数去乘以2的相应次方
不过次方要从0开始
位移位运算
如 UIViewAutoresizingFlexibleHeight = 1 << 4,
1.左移运算 1 << 4
将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。
1 转化为二进制为 :0000 0001
左移四位就为 :0001 0000
0001 0000 转化为十进制等于16
2.右移运算 90>>4
将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。操作数每右移一位,相当于该数除以2。
90转化为二进制为 :01011010
右移4位就是 :00000101
00000101 转化为十进制等于5
按位或运算符(|)
运算规则:0|0=0; 0|1=1; 1|0=1; 1|1=1;
即 :参加运算的两个二进制对应数位只要有一个为1,其值为1。
例如
[self todo:UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleHeight];
1.十进制1|4|16 转为二进制0000 0001 | 0000 0100 | 0001 0000 = 0001 0101,因此,1|4|16的十进制值得21
按位与运算符(&)
参加运算的两个数据,按二进制位进行“与”运算。
运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:两对应数位同时为“1”,结果才为“1”,否则为0
1.十进制3&5 转为二进制 0000 0011 & 0000 0101 = 0000 0001 因此,3&5的值得1
2.iOS在方法中的应用
-(void)todo:(UIViewAutoresizing)type{
if (type & UIViewAutoresizingFlexibleLeftMargin ) {
NSLog(@"UIViewAutoresizingFlexibleLeftMargin");
}
}
入参数type 为 UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleHeight
上文知道结果是 0001 0101,十进制值得21 UIViewAutoresizingFlexibleRightMargin为4
0001 0101 & UIViewAutoresizingFlexibleRightMargin = 0001 0101 & 0000 0100 =21&4 = 4 根据计算结果还是UIViewAutoresizingFlexibleRightMargin这个枚举
理论上更严谨的写法应该是 if ((type & UIViewAutoresizingFlexibleRightMargin)==UIViewAutoresizingFlexibleRightMargin )
要点 引用自effective Objective-C 2.0
应该用枚举来表示状态机的状态、传递给方法的选项以及状态码等值,给这些值起个易懂的名字。
如果把传递给某个方法的选项表示为枚举类型,而多个选项又可同时使用,那么就将各选项值定义为2的幂,以便通过按位或操作将其组合起来。
用NS_ENUM与NS_OPTIONS宏来定义枚举类型,并指明其底层数据类型。这样做可以确保枚举是用开发者所选的底层数据类型实现出来的,而不会采用编译器所选的类型。
在处理枚举类型的switch语句中不要实现default分支。这样的话,加入新枚举之后,编译器就会提示开发者:switch语句并未处理所有枚举。
实例demo https://github.com/shaojiankui/ShareBar-Demo
转载请注明:天狐博客 » iOS开发之位移枚举和按位或按位与运算