首先,NS_ENUM和NS_OPTIONS都是宏。 框架
Foundation框架中定義了一些輔助的宏,用這些宏來定義枚舉類型時,也能夠指定用於保存枚舉值的底層數據類型。這些宏具備向後兼容能力,若是目標平臺的編譯器支持新標準,那就使用新式語法,不然改用舊式語法。這些宏是用#define預處理指令來定義的。NS_ENUM 和 NS_OPTIONS的定義以下:spa
#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用與判斷編譯器是否支持新式枚舉。若是不支持,那麼就使用老式語法來定義枚舉。code
根據是否要將代碼按C++模式編譯,NS_OPTIONS宏的定義方式也有所不一樣。若是不按C++編譯,那麼其展開方式就和NS_ENUM相同。若按C++編譯,則展開後的代碼略有不一樣。緣由在於,用按位或運算來操做兩個枚舉值時,C++編譯模式的處理辦法與非C++模式不同。在用或運算操做兩個枚舉值時,C++認爲運算結果的數據類型應該是枚舉的底層數據類型,也就是NSUInteger,並且C++不容許將這個底層類型」隱式轉換「爲枚舉類型自己,因此,在C++模式下應該用NS_OPTIONS宏,以便省去類型轉換操做。blog
因此,凡是須要以按位或操做來組合的枚舉都應使用NS_OPTIONS定義。如果枚舉不須要互相組合,則應使用NS_ENUM來定義。編譯器