Using NSScanner to convert hex value to UIColor object

I’ve found that defining a custom UIColor using RGB values is a little counter intuitive compared to the more common hexadecimal notation used in CSS. This is particularly true if you want to define a color value in a file and don’t want to have to split it into three separate values.

For the most part, NSScanner has everything we need to parse data types (int, float, string etc) from a string.


The following is a simple method that will convert a hexadecimal color (e.g. #FFCC88) into an equivalent UIColor object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
- (UIColor *) colorForHex:(NSString *)hexColor {
	hexColor = [[hexColor stringByTrimmingCharactersInSet:
				 [NSCharacterSet whitespaceAndNewlineCharacterSet]
				] uppercaseString];  
 
    // String should be 6 or 7 characters if it includes '#'  
    if ([hexColor length] < 6) 
		return [UIColor blackColor];  
 
    // strip # if it appears  
    if ([hexColor hasPrefix:@"#"]) 
		hexColor = [cString substringFromIndex:1];  
 
    // if the value isn't 6 characters at this point return 
    // the color black	
    if ([hexColor length] != 6) 
		return [UIColor blackColor];  
 
    // Separate into r, g, b substrings  
    NSRange range;  
    range.location = 0;  
    range.length = 2; 
 
    NSString *rString = [hexColor substringWithRange:range];  
 
    range.location = 2;  
    NSString *gString = [hexColor substringWithRange:range];  
 
    range.location = 4;  
    NSString *bString = [hexColor substringWithRange:range];  
 
    // Scan values  
    unsigned int r, g, b;  
    [[NSScanner scannerWithString:rString] scanHexInt:&r];  
    [[NSScanner scannerWithString:gString] scanHexInt:&g];  
    [[NSScanner scannerWithString:bString] scanHexInt:&b];  
 
    return [UIColor colorWithRed:((float) r / 255.0f)  
                           green:((float) g / 255.0f)  
                            blue:((float) b / 255.0f)  
                           alpha:1.0f];  
 
}

Notice that I had to first separate our the hex values for the red, green, and blue components first as substrings and then apply the NSScanner to those substrings.

12 Comments

  1. Rodney,

    Thanks, this is very helpful.

    Cheers,
    Ivan

  2. @Joao Prado Maia

    Thanks for that tip … it is much more concise. Unfortunately it doesn’t deal with the issue that I was solving. In my case, the hex value was stored in a text file as a string. This file was something that was created by an entirely different application (thus no control over format). Given that the rgbvalue was a string, NSScanner made the most sense. All that said, I will definitely use your approach if I have a hex value in an integer value.

  3. Also note that the UIColor convenience constructor used above interprets the RGBA values in the device colorspace. This differs from the hex strings in CSS which are in sRGB.

    To use sRGB it looks like one has to go via CGColor.

  4. Ok, so I should have finished coding before replying here. It seems that the iPhone doesn’t support sRGB when going via CGColor: kCGColorSpaceSRGB is unavailable.

  5. This is my technique:

    #define HEXCOLOR(c) [UIColor colorWithRed:((c)&0xFF)/255.0 \
    green:((c>>8)&0xFF)/255.0 \
    blue:((c>>16)&0xFF)/255.0 \
    alpha:((c>>24)&0xFF)/255.0]
    unsigned int colorValue;
    [[NSScanner scannerWithString:colorString] scanHexInt:&colorValue];
    UIColor *color = HEXCOLOR(colorValue);

    A sample hex color string “7fcf0064” that should come out as light purple. “64” is red and “7f” is alpha.

    • Thanks for sharing this. Its a nice compact way of doing the stuff

Comments are closed.