I'm creating a category of UIColor where I have a set of colors that I want to access easily and then cache.
This is the basically how I create my colors:
#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;
}
However, repeating the above ten times is not really neat and dry so I'm trying to create a macro allowing me to do this easily.
Ideally, I'd like to replace the above with COLORGETTER(piglet, 234.0, 0.0, 130.0). I've had a go at it, but I can't get it to work. This is far as I got:
#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;\
}
However, the above doesn't work, as I can't figure out the #/## operators.
Any ideas?
There are two errors:
(instancetype *) should be (instancetype). Similar to id, this is already a pointer.##name##Color should be name##Color. You want to concatenate the name and "Color"
to a single token, but not the preceding token.So this seems to work:
#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;\
}
A few things
instancetype is already a pointer, don't use instancetype *. ## between identifieres - name ## Color, not ## name ## Color. dispatch_once block instead of the if.#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;\
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With