Create a UIColor from a hex string

Sometimes it can be useful to be able to create a UIColor from a hex value. Unfortunately there is no native way of doing that but fortunately for us, we can write a small extension to get the work done.

Here is the code:

extension UIColor {
    convenience init(hex: String, alpha: CGFloat = 1.0) {
        // 1
        let scanner = Scanner(string: hex)

        // 2
        let hexStart = hex[hex.startIndex] == "#"

        // 3
        let current = String.Index(utf16Offset: hexStart ? 1 : 0, in: hex)
        scanner.currentIndex = current
        
        // 4
        var rgb: UInt64 = 0

        // 5
        scanner.scanHexInt64(&rgb)

        // 6
        let r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0
        let g = CGFloat((rgb & 0xFF00) >> 8) / 255.0
        let b = CGFloat((rgb & 0xFF)) / 255.0
        
        // 7
        self.init(red: r, green: g, blue: b, alpha: alpha)
    }
}

Lets see what we did.

  1. Create a Scanner object from the hex string.
  2. Check if the hex string starts with an # sign.
  3. Create a new string index with an offset of either 0 or 1 depending on if the hex string started with # or not.
  4. Create an UInt64 with value zero.
  5. Call scanHexInt64() on the scanner to start scanning the rgb variable.
  6. Define three CGFloats called r, g, b with 16, 8 and zero bytes respectively.
  7. Call the initializer and init with the new values.

That is all it takes to initialize a UIColor from a hex string. Now you can initialize it like this:

let color = UIColor(hex: "#8523ff")

And to top it all off, we can add a neat way of getting the hex value from an existing color. Just extend the UIColor extension with this function:

func toHex() -> String {
    var r: CGFloat = 0.0
    var g: CGFloat = 0.0
    var b: CGFloat = 0.0
    var a: CGFloat = 0.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)
}

And now we can get the hex value from any color:

let red = UIColor.red
let hex = red.toHex()
print(hex) // Prints #ff0000