|
//
// NSString+Color.m
// NSStringColor
//
// Created by Nicolas Goutaland on 04/04/14.
// Copyright 2014 Nicolas Goutaland. All rights reserved.
//
// Color names : http://en.wikipedia.org/wiki/Web_colors
#import "NSString+Color.h"
@implementation NSString(Color)
#pragma mark - Class initialization
static __strong NSCache *colorsCache;
static __strong NSMutableDictionary *dicCustomColors;
static __strong NSRegularExpression *hexadecimalStringRegex;
+ (void)load
{
[super load];
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
colorsCache = [[NSCache alloc] init];
dicCustomColors = [[NSMutableDictionary alloc] init];
hexadecimalStringRegex = [NSRegularExpression regularExpressionWithPattern:NSString_Color_HEXADECIMAL_COLOR_STRING_REGEX
options:0
error:nil];
});
}
#pragma mark - Web color
+ (UIColor *)webColorForKey:(NSString *)webColorName
{
// Check cache first, to prevent unusful tests
NSString *key = [webColorName lowercaseString];
UIColor *color = [colorsCache objectForKey:key];
if (color)
return color;
static dispatch_once_t onceToken;
static __strong NSDictionary *dicWebColors = nil;
dispatch_once(&onceToken, ^{
dicWebColors =
@{
@"darkgreen": @"006400" ,
@"antiquewhite": @"FAEBD7" ,
@"aqua": @"00FFFF" ,
@"aquamarine": @"7FFFD4" ,
@"azure": @"F0FFFF" ,
@"beige": @"F5F5DC" ,
@"bisque": @"FFE4C4" ,
@"black": @"000000" ,
@"blanchedalmond": @"FFEBCD" ,
@"blue": @"0000FF" ,
@"blueviolet": @"8A2BE2" ,
@"brown": @"A52A2A" ,
@"burlywood": @"DEB887" ,
@"cadetblue": @"5F9EA0" ,
@"chartreuse": @"7FFF00" ,
@"chocolate": @"D2691E" ,
@"coral": @"FF7F50" ,
@"cornflowerblue": @"6495ED" ,
@"cornsilk": @"FFF8DC" ,
@"crimson": @"DC143C" ,
@"cyan": @"00FFFF" ,
@"darkblue": @"00008B" ,
@"darkcyan": @"008B8B" ,
@"darkgoldenrod": @"B8860B" ,
@"darkgray": @"A9A9A9" ,
@"darkgreen": @"006400" ,
@"darkkhaki": @"BDB76B" ,
@"darkmagenta": @"8B008B" ,
@"darkolivegreen": @"556B2F" ,
@"darkorange": @"FF8C00" ,
@"darkorchid": @"9932CC" ,
@"darkred": @"8B0000" ,
@"darksalmon": @"E9967A" ,
@"darkseagreen": @"8FBC8F" ,
@"darkslateblue": @"483D8B" ,
@"darkslategray": @"2F4F4F" ,
@"darkturquoise": @"00CED1" ,
@"darkviolet": @"9400D3" ,
@"deeppink": @"FF1493" ,
@"deepskyblue": @"00BFFF" ,
@"dimgray": @"696969" ,
@"dodgerblue": @"1E90FF" ,
@"firebrick": @"B22222" ,
@"floralwhite": @"FFFAF0" ,
@"forestgreen": @"228B22" ,
@"fuchsia": @"FF00FF" ,
@"gainsboro": @"DCDCDC" ,
@"ghostwhite": @"F8F8FF" ,
@"gold": @"FFD700" ,
@"goldenrod": @"DAA520" ,
@"gray": @"808080" ,
@"green": @"008000" ,
@"greenyellow": @"ADFF2F" ,
@"honeydew": @"F0FFF0" ,
@"hotpink": @"FF69B4" ,
@"indianred": @"CD5C5C" ,
@"indigo": @"4B0082" ,
@"ivory": @"FFFFF0" ,
@"khaki": @"F0E68C" ,
@"lavender": @"E6E6FA" ,
@"lavenderblush": @"FFF0F5" ,
@"lawngreen": @"7CFC00" ,
@"lemonchiffon": @"FFFACD" ,
@"lightblue": @"ADD8E6" ,
@"lightcoral": @"F08080" ,
@"lightcyan": @"E0FFFF" ,
@"lightgoldenrodyellow": @"FAFAD2" ,
@"lightgreen": @"90EE90" ,
@"lightgrey": @"D3D3D3" ,
@"lightpink": @"FFB6C1" ,
@"lightsalmon": @"FFA07A" ,
@"lightseagreen": @"20B2AA" ,
@"lightskyblue": @"87CEFA" ,
@"lightslategray": @"778899" ,
@"lightsteelblue": @"B0C4DE" ,
@"lightyellow": @"FFFFE0" ,
@"lime": @"00FF00" ,
@"limegreen": @"32CD32" ,
@"linen": @"FAF0E6" ,
@"magenta": @"FF00FF" ,
@"maroon": @"800000" ,
@"mediumaquamarine": @"66CDAA" ,
@"mediumblue": @"0000CD" ,
@"mediumorchid": @"BA55D3" ,
@"mediumpurple": @"9370DB" ,
@"mediumseagreen": @"3CB371" ,
@"mediumslateblue": @"7B68EE" ,
@"mediumspringgreen": @"00FA9A" ,
@"mediumturquoise": @"48D1CC" ,
@"mediumvioletred": @"C71585" ,
@"midnightblue": @"191970" ,
@"mintcream": @"F5FFFA" ,
@"mistyrose": @"FFE4E1" ,
@"moccasin": @"FFE4B5" ,
@"navajowhite": @"FFDEAD" ,
@"navy": @"000080" ,
@"oldlace": @"FDF5E6" ,
@"olive": @"808000" ,
@"olivedrab": @"6B8E23" ,
@"orange": @"FFA500" ,
@"orangered": @"FF4500" ,
@"orchid": @"DA70D6" ,
@"palegoldenrod": @"EEE8AA" ,
@"palegreen": @"98FB98" ,
@"paleturquoise": @"AFEEEE" ,
@"palevioletred": @"DB7093" ,
@"papayawhip": @"FFEFD5" ,
@"peachpuff": @"FFDAB9" ,
@"peru": @"CD853F" ,
@"pink": @"FFC0CB" ,
@"plum": @"DDA0DD" ,
@"powderblue": @"B0E0E6" ,
@"purple": @"800080" ,
@"red": @"FF0000" ,
@"rosybrown": @"BC8F8F" ,
@"royalblue": @"4169E1" ,
@"saddlebrown": @"8B4513" ,
@"salmon": @"FA8072" ,
@"sandybrown": @"F4A460" ,
@"seagreen": @"2E8B57" ,
@"seashell": @"FFF5EE" ,
@"sienna": @"A0522D" ,
@"silver": @"C0C0C0" ,
@"skyblue": @"87CEEB" ,
@"slateblue": @"6A5ACD" ,
@"slategray": @"708090" ,
@"snow": @"FFFAFA" ,
@"springgreen": @"00FF7F" ,
@"steelblue": @"4682B4" ,
@"tan": @"D2B48C" ,
@"teal": @"008080" ,
@"thistle": @"D8BFD8" ,
@"tomato": @"FF6347" ,
@"turquoise": @"40E0D0" ,
@"violet": @"EE82EE" ,
@"wheat": @"F5DEB3" ,
@"white": @"FFFFFF" ,
@"whitesmoke": @"F5F5F5" ,
@"yellow": @"FFFF00" ,
@"yellowgreen": @"9ACD32" };
});
// Try to retrieve webcolor code
NSString *colorCode = [dicWebColors objectForKey:key];
if (colorCode)
{
// Compute color
color = [colorCode colorFromRGBcode];
// Hold color
[colorsCache setObject:color
forKey:key];
}
return color;
}
#pragma mark - Custom colors
+ (void)registerColor:(UIColor *)color withKey:(NSString *)key
{
NSString *lcKey = [key lowercaseString];
[dicCustomColors setObject:color
forKey:lcKey];
[colorsCache removeObjectForKey:lcKey];
}
+ (void)clearRegisteredColorForKey:(NSString *)key
{
NSString *lcKey = [key lowercaseString];
[dicCustomColors removeObjectForKey:lcKey];
[colorsCache removeObjectForKey:lcKey];
}
+ (void)registerColors:(NSDictionary *)colors
{
NSMutableDictionary *updatedDic = [[NSMutableDictionary alloc] init];
UIColor *color;
id value;
NSString *lowercaseKey;
for (NSString *key in colors)
{
// Compute lowercase key
lowercaseKey = [key lowercaseString];
value = [colors objectForKey:key];
if ([value isKindOfClass:[UIColor class]])
{
[updatedDic setObject:value
forKey:lowercaseKey];
[colorsCache removeObjectForKey:lowercaseKey];
}
else if ([value isKindOfClass:[NSString class]])
{
// Try to extract color
color = [value representedColor];
if (color)
{
[updatedDic setObject:color
forKey:lowercaseKey];
[colorsCache removeObjectForKey:lowercaseKey];
}
}
}
// Add custom colors
[dicCustomColors addEntriesFromDictionary:updatedDic];
}
+ (UIColor *)registeredColorForKey:(NSString *)key
{
// Check cache first, to prevent unusful tests
NSString *lcKey = [key lowercaseString];
UIColor *color = [colorsCache objectForKey:lcKey];
if (color)
return color;
// Try to retrieve color
color = [dicCustomColors objectForKey:lcKey];
if (color)
{
// Hold color in cache
[colorsCache setObject:color
forKey:lcKey];
}
return color;
}
#pragma mark - Color
- (UIColor *)colorFromRGBcode
{
UIColor *color = [colorsCache objectForKey:self];
if (color)
return color;
unsigned int colorRGBhexaCode = 0;
// Scan hex number
NSScanner *scanner = [[NSScanner alloc] initWithString:self];
[scanner scanHexInt:&colorRGBhexaCode];
// Extract color components
unsigned int redColor = (colorRGBhexaCode >> 16);
unsigned int greenColor = (colorRGBhexaCode >> 8) & 0x00FF;
unsigned int blueColor = colorRGBhexaCode & 0x0000FF;
// Create result color
color = [UIColor colorWithRed:redColor/255.0 green:greenColor/255.0 blue:blueColor/255.0 alpha:1.0];
// Update cache
if (color)
{
[colorsCache setObject:color
forKey:self];
}
return color;
}
- (UIColor *)colorFromRGBAcode
{
UIColor *color = [colorsCache objectForKey:self];
if (color)
return color;
unsigned int colorRGBhexaCode = 0;
// Scan hex number
NSScanner *scanner = [[NSScanner alloc] initWithString:self];
[scanner scanHexInt:&colorRGBhexaCode];
// Extract color components
unsigned int redColor = (colorRGBhexaCode >> 24);
unsigned int greenColor = (colorRGBhexaCode >> 16) & 0x00FF;
unsigned int blueColor = (colorRGBhexaCode >> 8) & 0x0000FF;
unsigned int alphaColor = colorRGBhexaCode & 0x000000FF;
// Create result color
color = [UIColor colorWithRed:redColor/255.0f green:greenColor/255.0f blue:blueColor/255.0f alpha:alphaColor/255.0f];
// Update cache
if (color)
{
[colorsCache setObject:color
forKey:self];
}
return color;
}
- (UIColor *)colorFromName
{
UIColor *color = [colorsCache objectForKey:self];
if (color)
return color;
// Check custom colors
color = [[self class] registeredColorForKey:self];
if (color)
return color;
// Check for web color
color = [[self class] webColorForKey:self];
if (color)
return color;
SEL sel = NSSelectorFromString(self);
if ([UIColor respondsToSelector:sel])
{
color = [UIColor performSelector:sel];
}
else
{
SEL selColor = NSSelectorFromString([self stringByAppendingString:@"Color"]);
if ([UIColor respondsToSelector:selColor])
color = [UIColor performSelector:selColor];
}
// Update cache
if (color)
{
[colorsCache setObject:color
forKey:self];
}
return color;
}
- (UIColor *)representedColor
{
// Check cache first, to prevent unusful tests
UIColor *color = [colorsCache objectForKey:self];
if (color)
return color;
// Hexadecimal code, starting with #
if ([self rangeOfString:NSString_Color_HEXADECIMAL_PREFIX].location == 0)
{
// RGB Code
if (self.length == 7)
return [[self substringFromIndex:1] colorFromRGBcode];
// RGBA Code
return [[self substringFromIndex:1] colorFromRGBAcode];
}
// Hexadecimal code without #
NSRange firstMatch = [hexadecimalStringRegex rangeOfFirstMatchInString:self options:0 range:NSMakeRange(0, self.length)];
if (firstMatch.location == 0 && firstMatch.length == self.length)
{
if (self.length == 6)
return [self colorFromRGBcode];
return [self colorFromRGBAcode];
}
// Final test, check for selector name, web colors
return [self colorFromName];
}
@end
|