提要
花了幾天斷斷續(xù)續(xù)的讀了下SDWebImage的源碼,無意細(xì)心看了兩個宏定義NS_OPTIONS和NS_ENUM
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions)
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder)
兩種宏定義,雖然平時(shí)開發(fā)過程當(dāng)中大家采用第二種居多九杂,本著好奇鸵贬,研究了下這兩者的區(qū)別,以便識記屎媳。
本質(zhì)都是枚舉夺溢,用法就不扯淡了论巍,本篇主要看看二者的本質(zhì)差異。
Test示例
新建一個工程看看
typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
SDWebImageDownloaderLowPriority = 1 << 0
};
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
SDWebImageDownloaeExecutionOrder = 1 << 0
};
我們扒開她的衣服查看異同:
1.Xcode Preprocess
Xcode右上下拉點(diǎn)擊Preprocess將宏定義展開风响,展開后如下所示
typedef enum SDWebImageDownloaderOptions : NSUInteger SDWebImageDownloaderOptions; enum SDWebImageDownloaderOptions : NSUInteger {
SDWebImageDownloaderLowPriority = 1 << 0
};
typedef enum SDWebImageDownloaderExecutionOrder : NSInteger SDWebImageDownloaderExecutionOrder; enum SDWebImageDownloaderExecutionOrder : NSInteger {
SDWebImageDownloaeExecutionOrder = 1 << 0
};
這里你可以看到二者沒有任何差別嘉汰,那么Apple 為何要這么聲明呢?看來單純的展開并不能找到答案
2.深入Foundation
#define NS_ENUM(...) CF_ENUM(__VA_ARGS__)
#define NS_OPTIONS(_type, _name) CF_OPTIONS(_type, _name)
CF_ENUM状勤、CF_OPTIONS進(jìn)行了中轉(zhuǎn)鞋怀,那么我們繼續(xù)深入CoreFoundation/CFAvailability.h查看
// Enums and Options
#define __CF_ENUM_GET_MACRO(_1, _2, NAME, ...) NAME
#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum))
#define __CF_NAMED_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#define __CF_ANON_ENUM(_type) enum : _type
#if (__cplusplus)
#define CF_OPTIONS(_type, _name) _type _name; enum : _type
#else
#define CF_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
#endif
#else
#define __CF_NAMED_ENUM(_type, _name) _type _name; enum
#define __CF_ANON_ENUM(_type) enum
#define CF_OPTIONS(_type, _name) _type _name; enum
#endif
看到這里,差不多知道二者本質(zhì)區(qū)別持搜,多了cplusplus條件編譯密似,Apple這樣做根本上還是考慮到編譯器的兼容性
用法上NS_OPTIONS通常適合定義bitmask做位移組合運(yùn)算OR(|)、AND(&)朵诫,當(dāng)然在Objective-C編譯選項(xiàng)下也可以用NS_ENUM沒有任何區(qū)別辛友,但是編譯選項(xiàng)在C++\Objective-C++下就會出現(xiàn)問題,C++ 編譯選項(xiàng)下會導(dǎo)致類型不能強(qiáng)轉(zhuǎn)造成的編譯問題(譬如enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 不能執(zhí)行賦值操作)剪返,所以要使用NS_OPTIONS废累,做了編譯器兼容c++下都是NSInteger類型這樣就不會編譯出問題。