用枚舉表示狀態(tài)甜攀、選項

簡介

系統(tǒng)框架中頻繁使用到枚舉類型浑劳,在以一系列常量來表示狀態(tài)碼或可組合的選項時阱持,最好使用枚舉為其命名。
C++11標(biāo)準(zhǔn)擴(kuò)充了枚舉的特性呀洲,最新版系統(tǒng)框架使用了“強(qiáng)類型”(strong type)的枚舉紊选,OC也能得益于C++11標(biāo)準(zhǔn)。
枚舉只是一種常量命名方式道逗。編譯器會為枚舉分配一個獨(dú)有的編號,從0開始献烦,每個枚舉遞增1.實現(xiàn)枚舉所用的數(shù)據(jù)類型取決于編譯器滓窍,不過其二進(jìn)制位的個數(shù)必須能完全表示下枚舉編號才行。
C++11標(biāo)準(zhǔn)修訂了枚舉的某些特性巩那。其中一項改動是:可以指明用何種底層數(shù)據(jù)類型來保存保存枚舉類型的變量吏夯。

狀態(tài)

枚舉與狀態(tài)。狀態(tài)即横,同時只能有一種噪生。

typedef enum : NSUInteger {
    MyEnumValueA,
    MyEnumValueB,
    MyEnumValueC,
} MyEnum;
//MyEnum en = MyEnumValueA;


//NS_ENUM,定義狀態(tài)等普通枚舉
typedef NS_ENUM(NSUInteger, MyEnum){
    MyEnumValueA,
    MyEnumValueB,
    MyEnumValueC,
};

選項

選項东囚,同時可以有一種或一種以上跺嗽。定義選項的時候,若這些選項可以彼此組合页藻,則應(yīng)使用枚舉類型桨嫁。各選項之間可通過”按位或操作符“來組合。

typedef enum : NSUInteger {
    MyEnumValueNone = 0,
    MyEnumValueA = 1 << 0, //值為2的0次方 , 相當(dāng)于把1向左移動幾位
    MyEnumValueB = 1 << 1, //值為2的1次方
    MyEnumValueC = 1 << 2,
} MyEnum;

在每個枚舉值所對應(yīng)的二進(jìn)制表示中份帐,只有1個二進(jìn)制位的值是1璃吧。用”按位或操作符“可組合多個選項。

MyEnum en = MyEnumValueA | MyEnumValueB; //(按為或運(yùn)算 = 0011)
//用“與”運(yùn)算取出對應(yīng)位
if (en & MyEnumValueA) { // (0011 & 0001 = 0001 值為YES)
    NSLog(@“A”);
}

   0011
 & 0001
----------
   0001
//NS_OPTIONS废境,定義選項
typedef NS_OPTIONS(NSUInteger, MyEnum){
    MyEnumValueNone = 0,
    MyEnumValueA = 1 << 0,
    MyEnumValueB = 1 << 1,
    MyEnumValueC = 1 << 2,
};




OC中枚舉的使用

Foundation框架中定義了一些輔助的宏畜挨,用這些宏來定義枚舉類型時,也可以指定用于保存枚舉值的底層數(shù)據(jù)類型噩凹。這些宏具備向后兼容(backward compatibility)能力巴元,如果目標(biāo)平臺的編譯器支持新標(biāo)準(zhǔn),那就使用新式語法栓始,否則改用舊式語法务冕。這些宏是用#define預(yù)處理指令來定義的。typedef NS_ENUM幻赚,typedef NS_OPTIONS

這兩個宏的定義在Foundation.framework的NSObjCRuntime.h中:

#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum))  
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type  
#if (__cplusplus)  
#define NS_OPTIONS(_type, _name) _type _name; enum : _type  
#else  
#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type  
#endif  
#else  
#define NS_ENUM(_type, _name) _type _name; enum  
#define NS_OPTIONS(_type, _name) _type _name; enum  
#endif  

需要分別處理不同情況禀忆,所以上述代碼用多種方式來定義這兩個宏臊旭。第一個#if用來判斷編譯器是否支持新式枚舉。若不支持箩退,那么就用老式語法來定義枚舉离熏。
根據(jù)是否要將代碼按C++模式編譯 NS_OPTIONS宏的定義方式也有所不同。如果不按C++編譯戴涝,其展開方式就和NS_ENUM相同滋戳。若按C++編譯,則展開后代碼略有不同啥刻。原因在于奸鸯,用按位或運(yùn)算來操作兩個枚舉值時,C++編譯模式的處理辦法與非C++模式不一樣可帽。作為選項的枚舉值經(jīng)常需要按位或運(yùn)算來組合娄涩,在用或運(yùn)算操作兩個枚舉值時,C++認(rèn)為運(yùn)算結(jié)果的數(shù)據(jù)類型應(yīng)該是枚舉的底層數(shù)據(jù)類型映跟,也就是NSUInteger蓄拣。而C++不允許將這個底層類型”隱式轉(zhuǎn)換“為枚舉類型本身。因此努隙,凡是需要以按位或操作來組合的枚舉都應(yīng)使用NS_OPTIONS定義球恤。若是枚舉不需要互相組合,則應(yīng)使用NS_ENUM來定義荸镊。

我們總習(xí)慣在switch語句中加上default分支咽斧。若是使用枚舉來定義狀態(tài),則最好不要有default分支贷洲。如果稍后又加了一種狀態(tài)收厨,那么編譯器就會發(fā)出警告信息,提示新加入的狀態(tài)并未在switch分支中處理优构。假如寫上了default分支那么他就會處理這個新狀態(tài)诵叁,導(dǎo)致編譯器不發(fā)警告信息。用NS_ENUM定義其他枚舉類型時也要注意此問題钦椭。這樣能確保switch語句能正確處理所有樣式拧额。

總結(jié)

  1. 如果把傳遞給某個方法的選項表示為枚舉類型,而多個選項又可同時使用彪腔,那么就將各選項值定義為2的冪侥锦,以便通過按位或操作將其組合起來。
  2. 用NS_Enum 與 NS_OPTIONS 宏來定義枚舉類型德挣,并指明其底層數(shù)據(jù)類型恭垦。這樣做可以確保枚舉是用開發(fā)者所選的底層數(shù)據(jù)類型實現(xiàn)出來的,而不會采用編譯器所選的類型。
  3. 在處理枚舉類型的switch語句不要實現(xiàn)default分支番挺。這樣的話唠帝,加入新枚舉之后,編譯器就會提示開發(fā)者:switch語句并未處理所有枚舉玄柏。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末襟衰,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子粪摘,更是在濱河造成了極大的恐慌瀑晒,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徘意,死亡現(xiàn)場離奇詭異苔悦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)映砖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門间坐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人邑退,你說我怎么就攤上這事±统危” “怎么了地技?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長秒拔。 經(jīng)常有香客問我莫矗,道長,這世上最難降的妖魔是什么砂缩? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任作谚,我火速辦了婚禮,結(jié)果婚禮上庵芭,老公的妹妹穿的比我還像新娘妹懒。我一直安慰自己,他們只是感情好双吆,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布眨唬。 她就那樣靜靜地躺著,像睡著了一般好乐。 火紅的嫁衣襯著肌膚如雪匾竿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天蔚万,我揣著相機(jī)與錄音岭妖,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛昵慌,可吹牛的內(nèi)容都是我干的假夺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼废离,長吁一口氣:“原來是場噩夢啊……” “哼侄泽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蜻韭,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤悼尾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肖方,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闺魏,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年俯画,在試婚紗的時候發(fā)現(xiàn)自己被綠了析桥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡艰垂,死狀恐怖泡仗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情猜憎,我是刑警寧澤娩怎,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站胰柑,受9級特大地震影響截亦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜柬讨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一崩瓤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧踩官,春花似錦却桶、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蛋逾,卻和暖如春集晚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背区匣。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工偷拔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蒋院,地道東北人。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓莲绰,卻偏偏與公主長得像欺旧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蛤签,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容