24

Now I can convert a hex string to rgb color like this:

// Input is without the # ie : white = FFFFFF
+ (UIColor *)colorWithHexString:(NSString *)hexString
{
    unsigned int hex;
    [[NSScanner scannerWithString:hexString] scanHexInt:&hex];
    int r = (hex >> 16) & 0xFF;
    int g = (hex >> 8) & 0xFF;
    int b = (hex) & 0xFF;

    return [UIColor colorWithRed:r / 255.0f
                        green:g / 255.0f
                        blue:b / 255.0f
                        alpha:1.0f];
}

bu how can I convert rgb to hex string?

Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134
xushunwang
  • 283
  • 1
  • 2
  • 10

5 Answers5

44

Use this method :

- (NSString *)hexStringForColor:(UIColor *)color {
      const CGFloat *components = CGColorGetComponents(color.CGColor);
      CGFloat r = components[0];
      CGFloat g = components[1];
      CGFloat b = components[2];
      NSString *hexString=[NSString stringWithFormat:@"%02X%02X%02X", (int)(r * 255), (int)(g * 255), (int)(b * 255)];
      return hexString;
}
Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140
  • 3
    +1, but `CGFloat *components` should be `const CGFloat *components` and the cast is not needed. –  Dec 27 '12 at 09:00
  • @H2CO3 : ok. This code I used 3 years back while learning cocoa. Anyways Thanks `Carbonic Acid` :p . I always hated Chemistry but now I have started to love... – Anoop Vaidya Dec 27 '12 at 09:03
  • 1
    Your getting a bit a wrong color there because of the int casting. use lroundf() instead. – melbic Jun 12 '13 at 08:57
  • 4
    This will produce a bad hex with `UIColor.blackColor` and `UIColor.whiteColor` because there isn't a third component. – ray Apr 01 '16 at 19:58
  • There is issue when it has black color it gives me hex code of green color. Next answer works well – Shashi3456643 May 09 '18 at 00:14
20

Use this Extension of UIColor to get hexString from it.

  extension UIColor {
        func toHexString() -> String {
            var r:CGFloat = 0
            var g:CGFloat = 0
            var b:CGFloat = 0
            var a:CGFloat = 0

            getRed(&r, green: &g, blue: &b, alpha: &a)

            let rgb:Int = (Int)(r*255)<<16 | (Int)(g*255)<<8 | (Int)(b*255)<<0

            return String(format:"#%06x", rgb)
        }
    }
MobileMon
  • 8,341
  • 5
  • 56
  • 75
SPatel
  • 4,768
  • 4
  • 32
  • 51
  • Please add some explanation around the code so that people can understand it better. – James Monger Oct 13 '16 at 11:01
  • 1
    You need to understand some basics of Binary Operations: - He gets the value of red, green, blue, alpha between 0.0 and 1.0, and he multiplies by 255 (To have the value between 0 and 255.0). After that the '<<' operator does a shift operation of bytes to offset the Int value of the color: You don't need to move the blue color ( because it's already the right Int value), for the green you need to move just aside the blue value, because a Color value (0 to 255) is on 8 bytes you need to shift by 8. Red is the aside g so you need to move by 8 + 8 (16). %06x prints the hexadecimal value. – Beninho85 May 29 '17 at 19:27
9

Anoop answer is not correct as if you try it with [UIColor blackColor] it will return green color's hex string.
Reason is system is cleaver enough to save memory it will set

For black color
component[0] = 0 (r=0,g=0,b=0) and
component[1] = 1 (a=1).

For white color
component[0] = 1 (r=1,g=1,b=1) and
component[1] = 1 (a=1).


Use below category for UIColor to hex
UIColor+Utility.h
@interface UIColor (Utility)

/**
 Return representaiton in hex
 */
-(NSString*)representInHex;
@end

UIColor+Utility.m

@implementation UIColor (Utility)
-(NSString*)representInHex
{
    const CGFloat *components = CGColorGetComponents(self.CGColor);
    size_t count = CGColorGetNumberOfComponents(self.CGColor);

    if(count == 2){
        return [NSString stringWithFormat:@"#%02lX%02lX%02lX",
                lroundf(components[0] * 255.0),
                lroundf(components[0] * 255.0),
                lroundf(components[0] * 255.0)];
    }else{
        return [NSString stringWithFormat:@"#%02lX%02lX%02lX",
                lroundf(components[0] * 255.0),
                lroundf(components[1] * 255.0),
                lroundf(components[2] * 255.0)];
    }
}
@end

Jageen
  • 6,345
  • 2
  • 37
  • 56
  • You are right (+1), Anoop is just dealing RGBA based images, while you are also covering monochrome images. but actually there are even more possibilities: https://developer.apple.com/reference/coregraphics/cgcolorspacemodel?language=objc – vikingosegundo Nov 24 '16 at 01:12
6

This is the code that I used in Swift, please be aware that this seems to work fine when you send it a UIColor created with the rgba values, but returns some strange results when sending pre-defined colours like UIColor.darkGrayColor()

func hexFromUIColor(color: UIColor) -> String 
{
let hexString = String(format: "%02X%02X%02X", 
Int(CGColorGetComponents(color.CGColor)[0] * 255.0),
Int(CGColorGetComponents(color.CGColor)[1] *255.0),
Int(CGColorGetComponents(color.CGColor)[2] * 255.0))
return hexString
}
Dharmesh Porwal
  • 1,406
  • 2
  • 12
  • 21
Nathan Dries
  • 61
  • 1
  • 2
  • 5
    The strange results you get are because the system defined colors are not in the RGB color space, but in a grayscale color space. To prevent crashes or incorrect behavior you should check wether the color space matches (CGColorGetColorSpace()), or at least if the component count of the color space matches (CGColorGetNumberOfComponents()). – Alfonso Jun 30 '15 at 12:00
0

Objective-c UIColor category. This method can avoid situations like #FFFF00000000

- (id)hexString {
    CGFloat r, g, b, a;
    [self getRed:&r green:&g blue:&b alpha:&a];
    int rgb = (int)(r * 255.0f)<<16 | (int)(g * 255.0f)<<8 | (int)(b * 255.0f)<<0;
    if (a < 1) {
        rgb = (int)(a * 255.0f)<<24 | (int)(r * 255.0f)<<16 | (int)(g * 255.0f)<<8 | (int)(b * 255.0f)<<0;
    }
    
    return [NSString stringWithFormat:@"#%06x", rgb];
}
Le Ding
  • 695
  • 5
  • 7