复杂的预处理器宏

时间:2014-03-04 16:18:21

标签: objective-c macros c-preprocessor

我正在创建一个UIColor类别,其中我有一组颜色,我想轻松访问然后缓存。

这基本上就是我创建颜色的方式:

#define RGB(r, g, b) [self colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]

// [..]

+ (instancetype)pigletColor
{
    static UIColor *pigletColor = nil;
    if (!pigletColor) {
        pigletColor = RGB(237.0, 0.0, 130.0);
    }
    return pigletColor;
}

然而,重复上述十次并不是很干净,所以我试图创建一个允许我轻松完成此操作的宏。

理想情况下,我想将上述内容替换为COLORGETTER(piglet, 234.0, 0.0, 130.0)。我已经有了它,但我无法让它发挥作用。这是我得到的:

#define COLORGETTER(name, red, green, blue)\
+ (instancetype *)##name##Color\
{\
    static UIColor *##name##Color = nil;\
    if (!##name##Color) {\
        ##name##Color = RGB(red, green, blue);\
    }\
    return ##name##Color;\
}

但是,上述方法无效,因为我无法找出# / ##运营商。

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

有两个错误:

  • (instancetype *)应为(instancetype)。与id类似,这已经是一个指针。
  • ##name##Color应为name##Color。你想连接名称和“颜色” 单个令牌,但不是前面的令牌。

所以这似乎有效:

#define COLORGETTER(name, red, green, blue)\
    + (instancetype) name##Color\
    {\
        static UIColor * name##Color = nil;\
        if (!name##Color)\
        {\
            name##Color = RGB(red, green, blue);\
        }\
        return name##Color;\
    }

答案 1 :(得分:3)

一些事情

  1. instancetype已经是指针,请勿使用instancetype *
  2. 标识符之间只需要## - name ## Color,而不是## name ## Color
  3. 您应该使用dispatch_once块而不是if
  4. 可选,但您并不真正需要本地人的自定义名称。使用一个名称更容易。
  5. #define COLORGETTER(name, red, green, blue)\
    + (UIColor *)name##Color\
    {\
        static UIColor *color = nil;\
        static dispatch_once_t onceToken;\
        dispatch_once(&onceToken, ^{\
            color = RGB(red, green, blue);\
        });\
        return color;\    
    }