iOS開發(fā)-之-位移枚舉和按位或(|)按位與(&)運算

前言

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)出來的,而不會采用編譯器所選的類型。

在處理枚舉類型的switch語句中不要實現(xiàn)default分支。這樣的話,加入新枚舉之后,編譯器就會提示開發(fā)者:switch語句并未處理所有枚舉。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容