复杂的预处理宏

3

我正在创建一个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个回答

3

有两个错误:

  • (instancetype *) 应该改为 (instancetype)。类似于 id,这已经是一个指针。
  • ##name##Color 应该改为 name##Color。你想将名称和 "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;\
    }

不错!我的提交之后包括“37个添加和223个删除”。谢谢!我有24个颜色获取器可以简化。 :) - Alex

3

一些事情

  1. instancetype 已经是指针类型,不需要使用 instancetype *
  2. 只需要在标识符之间使用 ## - name ## Color,而不是 ## name ## Color
  3. 最好使用 dispatch_once 块代替 if 语句。
  4. 可选项,但你不真正需要为本地变量使用自定义名称。只使用一个名字更容易。
#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;\    
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接