SDWebImage源码后关于NS_OPTIONS和NS_ENU

作者: Frankxp | 来源:发表于2017-03-14 20:03 被阅读375次

    提要

    花了几天断断续续的读了下SDWebImage的源码,无意细心看了两个宏定义NS_OPTIONS和NS_ENUM

    typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions)
    typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder)
    

    两种宏定义,虽然平时开发过程当中大家采用第二种居多,本着好奇,研究了下这两者的区别,以便识记。
    本质都是枚举,用法就不扯淡了,本篇主要看看二者的本质差异。

    Test示例

    新建一个工程看看

    typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) {
        SDWebImageDownloaderLowPriority = 1 << 0
    };
    typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
        SDWebImageDownloaeExecutionOrder = 1 << 0
    };
    

    我们扒开她的衣服查看异同:

    1.Xcode Preprocess

    Xcode右上下拉点击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进行了中转,那么我们继续深入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
    

    看到这里,差不多知道二者本质区别,多了cplusplus条件编译,Apple这样做根本上还是考虑到编译器的兼容性

    用法上NS_OPTIONS通常适合定义bitmask做位移组合运算OR(|)、AND(&),当然在Objective-C编译选项下也可以用NS_ENUM没有任何区别,但是编译选项在C++\Objective-C++下就会出现问题,C++ 编译选项下会导致类型不能强转造成的编译问题(譬如enum MyEnumType aVar = MyEnumType1 | MyEnumType2; 不能执行赋值操作),所以要使用NS_OPTIONS,做了编译器兼容c++下都是NSInteger类型这样就不会编译出问题。

    相关文章

      网友评论

        本文标题:SDWebImage源码后关于NS_OPTIONS和NS_ENU

        本文链接:https://www.haomeiwen.com/subject/sitknttx.html