前言
Enumeration,enum,在程序設計語言中,一般用一個數(shù)值來代表某一狀態(tài),這種處理方法不直觀,易讀性差。如果能在程序中用自然語言中有相應含義的單詞來代表某一狀態(tài),則程序就很容易閱讀和理解。也就是說,事先考慮到某一變量可能取的值,盡量用自然語言中含義清楚的單詞來表示它的每一個值,這種方法稱為枚舉方法,用這種方法定義的類型稱枚舉類型。
命名
定義的枚舉類型名稱通常與項目的類文件前綴相同,或者是類庫框架縮寫,或者跟隨具體業(yè)務名,如果開頭是縮寫要大寫表示,跟隨其后的命名應采用駝峰命名法則,命名應準確表述枚舉表示的意義,枚舉中各個值都應以定義的枚舉類型開頭,其后跟隨各個枚舉值對應的狀態(tài)、選項或者狀態(tài)碼
狀態(tài)與選項(states and options)
狀態(tài)
同時只能有一種,如“RecordPause”,“RecordEnd”,不可能同時Record是RecordPause和RecordEnd。如下:
typedef NS_ENUM(NSUInteger, VoiceRecordStatus){
VoiceRecordStatusPrepare = 0,
VoiceRecordStatusIng,
VoiceRecordStatusPause,
VoiceRecordStatusEnd
};
由于每種狀態(tài)都用一個便于理解的值來表示,所以這樣寫出來的代碼更易讀懂。編譯器會為枚舉分配一個獨有的編號,從0開始,每個枚舉遞增1
選項
定義選項的時候。若這些選項可以彼此組合,則更應如此。只要枚舉定義得對,各選項之間就可通過“按位或操作符”(bitwise OR operator)來組合。例如,iOS UI框架中有如下枚舉類型,用來表示某個視圖應該如何在水平或垂直方向上調整大小
位移枚舉(可復選的枚舉) 使用位移實現(xiàn)選項變量
本文使用 Autoresizing 的系統(tǒng)枚舉UIViewAutoresizing作為基礎進行講述:
以下位移已經(jīng)提前計算出來了二進制與十進制值為了方便下文使用
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing){ 二進制值 十進制
UIViewAutoresizingNone = 0, 00000000 0
UIViewAutoresizingFlexibleLeftMargin = 1<<0, 00000001 1
UIViewAutoresizingFlexibleWidth = 1<<1, 00000010 2
UIViewAutoresizingFlexibleRightMargin = 1<<2, 00000100 4
UIViewAutoresizingFlexibleTopMargin = 1<<3, 00001000 8
UIViewAutoresizingFlexibleHeight = 1<<4, 00010000 16
UIViewAutoresizingFlexibleBottomMargin = 1<<5 00100000 32
};
使用枚舉定義選項,每個選項均可啟用或禁用,使用上述方式來定義枚舉值,每個枚舉值所對應的二進制表示中,只有1個二進制位的值是1。用“按位或操作符”可組合多個選項
用( | )來隔開
aView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin;
而且每一個枚舉對應的邏輯都會覆蓋到
實例
- (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");
}
}
- (void)viewDidLoad {
[superviewDidLoad];
//Do any additional setup after loading the view, typically from anib.
[selftodo:UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleHeight];
}
結果輸出
UIViewAutoresizingFlexibleLeftMarginUIViewAutoresizingFlexibleRightMarginUIViewAutoresizingFlexibleHeight
二進制轉十進制
1101(2進制)= 1x20+0x21+1x22+1x23=1+0+4+8=13轉化成十進制要從右到左用二進制的每個數(shù)去乘以2的相應次方不過次方要從0開始
位移位運算
如 UIViewAutoresizingFlexibleHeight = 1 << 4,
1.左移運算 1 << 4
將一個運算對象的各二進制位全部左移若干位(左邊的二進制位丟棄,右邊補0)。
1 轉化為二進制為 :0000 0001
左移四位就為 :0001 0000
0001 0000 轉化為十進制等于16
2.右移運算 90>>4
將一個數(shù)的各二進制位全部右移若干位,正數(shù)左補0,負數(shù)左補1,右邊丟棄。操作數(shù)每右移一位,相當于該數(shù)除以2。
90轉化為二進制為 :01011010
右移4位就是 :00000101
00000101 轉化為十進制等于5
按位或運算符(|)
運算規(guī)則:0|0=0; 0|1=1; 1|0=1; 1|1=1;
即 :參加運算的兩個二進制對應數(shù)位只要有一個為1,其值為1
例如:
[self todo:UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleHeight];
1.十進制1|4|16 轉為二進制0000 0001 | 0000 0100 | 0001 0000 = 0001 0101,因此,1|4|16的十進制值得21
按位與運算符(&)
參加運算的兩個數(shù)據(jù),按二進制位進行“與”運算。
運算規(guī)則:0&0=0; 0&1=0; 1&0=0; 1&1=1;
即:兩對應數(shù)位同時為“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");
}
}
傳入?yún)?shù)type 為 UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleHeight
上文知道結果是 0001 0101,十進制值得21
UIViewAutoresizingFlexibleRightMargin為4
0001 0101 & UIViewAutoresizingFlexibleRightMargin = 0001 0101 & 0000 0100 =21 & 4 = 4
根據(jù)計算結果還是UIViewAutoresizingFlexibleRightMargin這個枚舉
所以理論上更嚴謹?shù)膶懛☉撌?
if ((type & UIViewAutoresizingFlexibleRightMargin) == UIViewAutoresizingFlexibleRightMargin){
}
要點 引用自effective Objective-C 2.0
應該用枚舉來表示狀態(tài)機的狀態(tài)、傳遞給方法的選項以及狀態(tài)碼等值,給這些值起個易懂的名字。
如果把傳遞給某個方法的選項表示為枚舉類型,而多個選項又可同時使用,那么就將各選項值定義為2的冪,以便通過按位或操作將其組合起來。
用NS_ENUM與NS_OPTIONS宏來定義枚舉類型,并指明其底層數(shù)據(jù)類型。這樣做可以確保枚舉是用開發(fā)者所選的底層數(shù)據(jù)類型實現(xiàn)出來的,而不會采用編譯器所選的類型。