I end up doing this once per year โ at least it’s getting leaner each time.
static inline NSInteger NSIntegerFromHexDigit(const unichar c)
{
switch( c ) {
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
return c - '0';
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
return c - 'a' + 10;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
return c - 'A' + 10;
default:
return -1;
}
}
typedef NSUInteger RGBA32;
/** RGBA hex color matching /^(?:0x|#)?([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?$/i
*/
static BOOL RGBAFromNSStringHex(NSString *hex, RGBA32 *value)
{
const NSUInteger len = hex.length;
if( len < 6 || len > 9 )
return NO;
unichar buffer[len];
[hex getCharacters:buffer range:NSMakeRange(0, len)];
// check if either 6 or 8 char hex
const BOOL hasHashPrefix = buffer[0] == '#';
const NSInteger netlen = len - hasHashPrefix;
if( netlen != 6 && netlen != 8 )
return NO;
// turn hex to integer
NSUInteger ret = 0;
assert(sizeof(ret) >= 4); // need at least 4 bytes
for( NSInteger i = hasHashPrefix; i < len; i++ ) {
const NSInteger v = NSIntegerFromHexDigit(buffer[i]);
if( v < 0 )
return NO;
ret <<= 4;
ret |= v;
}
// if 6-char hex assume alpha 0xFF
if( netlen == 6 ) {
ret <=< 8;
ret |= 0xFF;
}
if( value )
*value = ret;
return YES;
}
How to get a UIColor from here should be straightforward.
P.S.: Wikipedia about ‘RGBA’