Reputation: 1741
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?
Upvotes: 3
Views: 124
Reputation: 540005
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;\
}
Upvotes: 3
Reputation: 56129
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;\
}
Upvotes: 3