How to convert UIColor to HEX and display in NSLog

IosObjective CSwiftIphoneUicolor

Ios Problem Overview


I have checked several links on how to convert UIColor codes to HEX however I am not sure on how to call to the method to display them in NSLog. I haven't got the reputation to comment so posting as a question is my last resort. I want it to display when I run my app in the log.

Second, where do I input the RGB color number ( R = 30, G = 171, B = 13)? I see that all examples use Array [0], [1], [2] which normally refers to index position, so where do I add the color values?

I have this code:

- (NSString *) hexFromUIColor:(UIColor *)color {

    if (CGColorGetNumberOfComponents(color.CGColor) < 4) {
        const CGFloat *components = CGColorGetComponents(color.CGColor);
        color = [UIColor colorWithRed:components[30] green:components[141] blue:components[13] alpha:components[1]];
    }
    if (CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor)) != kCGColorSpaceModelRGB) {
        return [NSString stringWithFormat:@"#FFFFFF"];
    }
    return [NSString stringWithFormat:@"#%02X%02X%02X", (int)((CGColorGetComponents(color.CGColor))[0]*255.0), (int)((CGColorGetComponents(color.CGColor))[1]*255.0), (int)((CGColorGetComponents(color.CGColor))[2]*255.0)];

}

Links I have checked:

https://stackoverflow.com/questions/10285365/hex-color-from-uicolor/13134326#13134326

https://stackoverflow.com/questions/3805177/how-to-convert-hex-rgb-color-codes-to-uicolor

I have tried to call the method in viewDidLoad however it wont work without UIColor. I am sure it's something simple.

Thanks to anyone who answers.

What is the code I use in my viewDidLoad to call to this method in order to display in NSLog?

Ios Solutions


Solution 1 - Ios

Swift 5:

func hexStringFromColor(color: UIColor) -> String {
    let components = color.cgColor.components
    let r: CGFloat = components?[0] ?? 0.0
    let g: CGFloat = components?[1] ?? 0.0
    let b: CGFloat = components?[2] ?? 0.0
        
    let hexString = String.init(format: "#%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)), lroundf(Float(b * 255)))
    print(hexString)
    return hexString
 }

func colorWithHexString(hexString: String) -> UIColor {
    var colorString = hexString.trimmingCharacters(in: .whitespacesAndNewlines)
    colorString = colorString.replacingOccurrences(of: "#", with: "").uppercased()
    
    print(colorString)
    let alpha: CGFloat = 1.0
    let red: CGFloat = self.colorComponentFrom(colorString: colorString, start: 0, length: 2)
    let green: CGFloat = self.colorComponentFrom(colorString: colorString, start: 2, length: 2)
    let blue: CGFloat = self.colorComponentFrom(colorString: colorString, start: 4, length: 2)
    
    let color = UIColor(red: red, green: green, blue: blue, alpha: alpha)
    return color
}

func colorComponentFrom(colorString: String, start: Int, length: Int) -> CGFloat {
            
    let startIndex = colorString.index(colorString.startIndex, offsetBy: start)
    let endIndex = colorString.index(startIndex, offsetBy: length)
    let subString = colorString[startIndex..<endIndex]
    let fullHexString = length == 2 ? subString : "\(subString)\(subString)"
    var hexComponent: UInt32 = 0

    guard Scanner(string: String(fullHexString)).scanHexInt32(&hexComponent) else {
        return 0
    }
    let hexFloat: CGFloat = CGFloat(hexComponent)
    let floatValue: CGFloat = CGFloat(hexFloat / 255.0)
    print(floatValue)
    return floatValue
}

How to use

let red =  CGFloat(30.0)
let green =  CGFloat(171.0)
let blue =  CGFloat(13.0)
let alpha =  CGFloat(1.0)

let color = UIColor(red: CGFloat(red/255.0), green: CGFloat(green/255.0), blue: CGFloat(blue / 255.0), alpha: alpha)
let colorCode = self.hexStringFromColor(color: color)
print(colorCode)
        
let resultColor = self.colorWithHexString(hexString: colorCode)
print(resultColor)

Objective-C:

- (NSString *)hexStringFromColor:(UIColor *)color {
    const CGFloat *components = CGColorGetComponents(color.CGColor);
    
    CGFloat r = components[0];
    CGFloat g = components[1];
    CGFloat b = components[2];
    
    return [NSString stringWithFormat:@"#%02lX%02lX%02lX",
            lroundf(r * 255),
            lroundf(g * 255),
            lroundf(b * 255)];
}

After getting hex code string, Call below method to get UIColor

- (UIColor *) colorWithHexString: (NSString *) hexString
{
    NSString *colorString = [[hexString stringByReplacingOccurrencesOfString: @"#" withString: @""] uppercaseString];

    NSLog(@"colorString :%@",colorString);
    CGFloat alpha, red, blue, green;
    
    // #RGB
    alpha = 1.0f;
    red   = [self colorComponentFrom: colorString start: 0 length: 2];
    green = [self colorComponentFrom: colorString start: 2 length: 2];
    blue  = [self colorComponentFrom: colorString start: 4 length: 2];
    
    return [UIColor colorWithRed: red green: green blue: blue alpha: alpha];
}


- (CGFloat) colorComponentFrom: (NSString *) string start: (NSUInteger) start length: (NSUInteger) length {
    NSString *substring = [string substringWithRange: NSMakeRange(start, length)];
    NSString *fullHex = length == 2 ? substring : [NSString stringWithFormat: @"%@%@", substring, substring];
    unsigned hexComponent;
    [[NSScanner scannerWithString: fullHex] scanHexInt: &hexComponent];
    return hexComponent / 255.0;
}

How to use

// ( R = 30, G = 171, B = 13)? 
CGFloat red = 30.0;
CGFloat green = 171.0;
CGFloat blue = 13.0; 
CGFloat alpha = 255.0
UIColor *color = [UIColor colorWithRed:(red/255.0) green:(green/255.0) blue:(blue/255.0) alpha:(alpha/255.0)];
NSString *colorCode = [self hexStringFromColor:color];
NSLog(@"Color Code: %@", colorCode);
       
UIColor *resultColor = [self colorWithHexString:colorCode];

Solution 2 - Ios

And finally the version which works with alpha-component and uses right multiplier
extension UIColor {
    var hexString: String? {
        var red: CGFloat = 0
        var green: CGFloat = 0
        var blue: CGFloat = 0
        var alpha: CGFloat = 0

        let multiplier = CGFloat(255.999999)

        guard self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) else {
            return nil
        }

        if alpha == 1.0 {
            return String(
                format: "#%02lX%02lX%02lX",
                Int(red * multiplier),
                Int(green * multiplier),
                Int(blue * multiplier)
            )
        }
        else {
            return String(
                format: "#%02lX%02lX%02lX%02lX",
                Int(red * multiplier),
                Int(green * multiplier),
                Int(blue * multiplier),
                Int(alpha * multiplier)
            )
        }
    }
}

Solution 3 - Ios

Kampai's answer works for RGB colors, but not for monochrome (UIColor colorWithWhite:alpha:). It also doesn't handle alpha, which HEX supports. Here's a slightly modified version of hexStringFromColor:

+ (NSString *)hexStringFromColor:(UIColor *)color
{
    CGColorSpaceModel colorSpace = CGColorSpaceGetModel(CGColorGetColorSpace(color.CGColor));
    const CGFloat *components = CGColorGetComponents(color.CGColor);
    
    CGFloat r, g, b, a;
    
    if (colorSpace == kCGColorSpaceModelMonochrome) {
        r = components[0];
        g = components[0];
        b = components[0];
        a = components[1];
    }
    else if (colorSpace == kCGColorSpaceModelRGB) {
        r = components[0];
        g = components[1];
        b = components[2];
        a = components[3];
    }
    
    return [NSString stringWithFormat:@"#%02lX%02lX%02lX%02lX",
            lroundf(r * 255),
            lroundf(g * 255),
            lroundf(b * 255),
            lroundf(a * 255)];
}

Solution 4 - Ios

Other Swift answers crash for UIColors like white, where there are only 2 components returned by CGColor.

Here's a Swift 4 version that does not have that problem and also returns transparency information in the end of the string if that is required (web format).

The color is first converted to the sRGB colorspace before generating the HEX String to work properly even with Grayscale or other color spaces.

For example:

White will return #FFFFFF

White with 50% opacity will return #FFFFFF7F

extension UIColor {
    var hexString: String {
		let cgColorInRGB = cgColor.converted(to: CGColorSpace(name: CGColorSpace.sRGB)!, intent: .defaultIntent, options: nil)!
        let colorRef = cgColorInRGB.components
        let r = colorRef?[0] ?? 0
        let g = colorRef?[1] ?? 0
        let b = ((colorRef?.count ?? 0) > 2 ? colorRef?[2] : g) ?? 0
        let a = cgColor.alpha
	
        var color = String(
            format: "#%02lX%02lX%02lX",
            lroundf(Float(r * 255)),
            lroundf(Float(g * 255)),
            lroundf(Float(b * 255))
        )

        if a < 1 {
            color += String(format: "%02lX", lroundf(Float(a * 255)))
        }

        return color
    }
}

> OLD VERSION

This version did not work properly with certain colors in non-RGB color spaces.

extension UIColor {
	var hexString: String {
    	let colorRef = cgColor.components
    	let r = colorRef?[0] ?? 0
    	let g = colorRef?[1] ?? 0
    	let b = ((colorRef?.count ?? 0) > 2 ? colorRef?[2] : g) ?? 0
    	let a = cgColor.alpha

    	var color = String(
	    	format: "#%02lX%02lX%02lX",
	    	lroundf(Float(r * 255)),
	    	lroundf(Float(g * 255)),
	    	lroundf(Float(b * 255))
	    )

	    if a < 1 {
			color += String(format: "%02lX", lroundf(Float(a)))
    	}

		return color
	}
}

Solution 5 - Ios

Swift way:

extension UIColor {
    var hexString: String {
        cgColor.components![0..<3]
            .map { String(format: "%02lX", Int($0 * 255)) }
            .reduce("#", +)
    }
}

If you need hex with alpha just remove [0..<3] from code.

Another safer implementation, that works fine with one component colors (like UIColor.white, UIColor.black):

    var hexString: String {
        var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0
        getRed(&r, green: &g, blue: &b, alpha: nil)
        return [r, g, b].map { String(format: "%02lX", Int($0 * 255)) }.reduce("#", +)
    }

Solution 6 - Ios

In Swift, I simply created an extension to UIColor...

extension UIColor
{

    var hexString:NSString {
	    let colorRef = CGColorGetComponents(self.CGColor)
	
	    let r:CGFloat = colorRef[0]
	    let g:CGFloat = colorRef[1]
	    let b:CGFloat = colorRef[2]
	
	    return NSString(format: "#%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)), lroundf(Float(b * 255)))
    }
}

Solution 7 - Ios

extension UIColor {
    var hexString: String? {
        guard let components = self.cgColor.components else { return nil }

        let red = Float(components[0])
        let green = Float(components[1])
        let blue = Float(components[2])
        return String(format: "#%02lX%02lX%02lX", lroundf(red * 255), lroundf(green * 255), lroundf(blue * 255))
    }
}

Solution 8 - Ios

Based on Kampai's answer, here's the SwiftUI version.

extension Color {
    func hexString() -> String {
        let components = self.cgColor?.components
        let r: CGFloat = components?[0] ?? 0.0
        let g: CGFloat = components?[1] ?? 0.0
        let b: CGFloat = components?[2] ?? 0.0

        let hexString = String.init(format: "#%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)), lroundf(Float(b * 255)))
        return hexString
    }
}

Solution 9 - Ios

This is the correct order if you need the colors for Android. the alpha goes first:

extension UIColor {
    var hexString: String? {
        var red: CGFloat = 0
        var green: CGFloat = 0
        var blue: CGFloat = 0
        var alpha: CGFloat = 0
        
        let multiplier = CGFloat(255.999999)
        
        guard self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) else {
            return nil
        }
        
        if alpha == 1.0 {
            return String(
                format: "#%02lX%02lX%02lX",
                Int(red * multiplier),
                Int(green * multiplier),
                Int(blue * multiplier)
            )
        }
        else {
            return String(
                format: "#%02lX%02lX%02lX%02lX",
                Int(alpha * multiplier),
                Int(red * multiplier),
                Int(green * multiplier),
                Int(blue * multiplier)
            )
        }
    }
}

Then call as:

debugPrint("testColor > ", self.testColor().hexString!)

Solution 10 - Ios

Or you can use .hexCode if use this extension for UIColor.

Like this:

extension UIColor {
    var hexCode: String {
        get{
            let colorComponents = self.cgColor.components!
            if colorComponents.count < 4 {
                return String(format: "%02x%02x%02x", Int(colorComponents[0]*255.0), Int(colorComponents[0]*255.0),Int(colorComponents[0]*255.0)).uppercased()
            }
            return String(format: "%02x%02x%02x", Int(colorComponents[0]*255.0), Int(colorComponents[1]*255.0),Int(colorComponents[2]*255.0)).uppercased()
        }
    }
}

var myColor: UIColor?
myColor = UIColor(red: 1, blue: 1, green: 1, alpha: 1.0)
print(myColor!.hexCode) // output: 
// if you use API, you can do something like this:
print("#\(myColor!.hexCode)") // output: #FFFFFF

Solution 11 - Ios

The swift 2 answer converted to swift 3

var hexString: String {
    let components = self.cgColor.components
    
    let red = Float((components?[0])!)
    let green = Float((components?[1])!)
    let blue = Float((components?[2])!)
    return String(format: "#%02lX%02lX%02lX", lroundf(red * 255), lroundf(green * 255), lroundf(blue * 255))
}

Solution 12 - Ios

Potential Trap When Dealing With Alpha: HEX strings come in different formats, some have their alpha at the start of the hex string and other formats have it at the end. Depending on your background you may have a different idea of how the hex string is formatted. For Android developers it will likely be with the alpha at the start, for Web developers it will likely be at the end of the string. SO ALWAYS STATE THE FORMAT OF THE HEX STRING to avoid confusion. Android hex strings are required to have the alpha at the start. So that is a trap people may fall into when it comes to hex strings (I did) and is thus important to say what the expected format is. So if you are developing an app for both iOS and Android what out for this trap.

Links: https://en.wikipedia.org/wiki/RGBA_color_space for details on why a HEX string maybe formatted in different ways, some cases with the alpha at the start. Android links https://developer.android.com/reference/android/graphics/Color.html and https://gist.github.com/lopspower/03fb1cc0ac9f32ef38f4

PLEASE NOTE FOR #AARRGGBB Hex string format Use the following code so the Alpha is at the start of the string.

(Note: if color == null black is returned).

+(NSString*)hexStringFromColor:(UIColor *)color
{
    
    CGFloat r = 0, g = 0, b = 0, a = 1;
    
    if (color) {
        [color getRed:&r green:&g blue:&b alpha:&a];
    }

    return [NSString stringWithFormat:@"#%02lX%02lX%02lX%02lX",            lroundf(a * 255.0),            lroundf(r * 255.0),            lroundf(g * 255.0),            lroundf(b * 255.0)            ];

}

Solution 13 - Ios

Swift 5

extension Collection {
    public subscript(safe index: Index) -> Element? {
        return startIndex <= index && index < endIndex ? self[index] : nil
    }
}
extension UIColor {
	var hexString: String {
		let components = cgColor.components
		let r: CGFloat = components?[safe: 0] ?? 0.0
		let g: CGFloat = components?[safe: 1] ?? 0.0
		let b: CGFloat = components?[safe: 2] ?? 0.0

		let hexString = String(format: "#%02lX%02lX%02lX", lroundf(Float(r * 255)), lroundf(Float(g * 255)),
							   lroundf(Float(b * 255)))

		return hexString
	}
}

Solution 14 - Ios

SwiftUI

P3 Color to HEX

extension Color {

    var hex: String {
        guard let colorSpace = CGColorSpace(name: CGColorSpace.displayP3), let color = UIColor(self).cgColor.converted(to: colorSpace, intent: .defaultIntent, options: nil),
          let components = color.components, 3 <= components.count else { return "" }

        return String(format: "#%02lX%02lX%02lX%02lX", lroundf(Float(components[0] * 255)), lroundf(Float(components[1] * 255)), lroundf(Float(components[2] * 255)), lroundf(Float(components[3] * 255)))
     }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionApp Dev GuyView Question on Stackoverflow
Solution 1 - IosKampaiView Answer on Stackoverflow
Solution 2 - IosValentin SherginView Answer on Stackoverflow
Solution 3 - IosJeffView Answer on Stackoverflow
Solution 4 - Iosm_katsifarakisView Answer on Stackoverflow
Solution 5 - IosArtem SydorenkoView Answer on Stackoverflow
Solution 6 - IosJoel KopelioffView Answer on Stackoverflow
Solution 7 - IosIsuruView Answer on Stackoverflow
Solution 8 - IosIvan CantarinoView Answer on Stackoverflow
Solution 9 - IosMr TView Answer on Stackoverflow
Solution 10 - IosMostafa AbbastabarView Answer on Stackoverflow
Solution 11 - IosHarisView Answer on Stackoverflow
Solution 12 - IosGrant LuckView Answer on Stackoverflow
Solution 13 - IososcarrView Answer on Stackoverflow
Solution 14 - IosDenView Answer on Stackoverflow