Get RGB from SwiftUI Color Picker

The new ColorPicker for SwiftUI initializes with a Binding<Color>.

A Color, however, only gets resolved by SwiftUI "just before using it in a given environment".

How do I get the RGB values (or a UIColor) from the SwiftUI color picker?
The UIKit version UIColorPickerViewController has a [selectedColor](https://developer.apple.com/documentation/uikit/uicolorpickerviewcontroller/3600466-selectedcolor) property that one could read.

Is there any way to use the SwiftUI color picker and read the actually value selected by the user?

Replies

Unfortunately I believe the only alternative without using a UIColorPickerViewController is to convert the description (which returns a hexadecimal value) property of the Color from HEX to RGBa.
In iOS 14+ or in other new SDKs, you can use an initializer of UIColor taking Color.

init(Color)
Xcode 12 beta 3: ColorPicker won't run on Simulator, so run it on your device.

struct ContentView: View {
    @State private var drawSwiftUIColor: Color = Color.red
    @State private var drawOpacity: Double = 1.0
    @State private var drawUIColor: UIColor = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0)
    @State private var drawHexNumber: String = "#FF0000"

    var body: some View {
        VStack {
            Spacer()
            ColorPicker("", selection: $drawSwiftUIColor, supportsOpacity: true)
                .scaleEffect(2)
                .offset(x: 28 - UIScreen.main.bounds.width, y: -15)
                .onChange(of: drawSwiftUIColor) { newValue in
                    getColorsFromPicker(pickerColor: newValue)
                }

                // Use this only if you are initializing the picker with UIColor, otherwise delete the onAppear()
                .onAppear() {
                    //resetColorPickerWithUIColor()
                }

            Spacer()

            Text("SwiftUI Color").bold().foregroundColor(drawSwiftUIColor).opacity(drawOpacity)

            Text("UI Color").bold().foregroundColor(Color(drawUIColor))

            Text("Hex Number: \(drawHexNumber)").bold()
        }
    }


    func getColorsFromPicker(pickerColor: Color) {
        let colorString = "\(pickerColor)"
        let colorArray: [String] = colorString.components(separatedBy: " ")

        if colorArray.count > 1 {
            var r: CGFloat = CGFloat((Float(colorArray[1]) ?? 1))
            var g: CGFloat = CGFloat((Float(colorArray[2]) ?? 1))
            var b: CGFloat = CGFloat((Float(colorArray[3]) ?? 1))
            let alpha: CGFloat = CGFloat((Float(colorArray[4]) ?? 1))

            if (r < 0.0) {r = 0.0}
            if (g < 0.0) {g = 0.0}
            if (b < 0.0) {b = 0.0}

            if (r > 1.0) {r = 1.0}
            if (g > 1.0) {g = 1.0}
            if (b > 1.0) {b = 1.0}

            // Update UIColor
            drawUIColor = UIColor(red: r, green: g, blue: b, alpha: alpha)
            // Update Opacity
            drawOpacity = Double(alpha)

            // Update hex
            let rgb:Int = (Int)(r*255)<<16 | (Int)(g*255)<<8 | (Int)(b*255)<<0
            drawHexNumber = String(format: "#%06X", rgb)
        }
    }


    func resetColorPickerWithUIColor() {
        let color: UIColor = drawUIColor
        let r: Double = Double(color.rgba.red)
        let g: Double = Double(color.rgba.green)
        let b: Double = Double(color.rgba.blue)
        drawSwiftUIColor = Color(red: r, green: g, blue: b, opacity: drawOpacity)
    }
}

extension UIColor {
    var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
        var red: CGFloat = 0
        var green: CGFloat = 0
        var blue: CGFloat = 0
        var alpha: CGFloat = 0

        getRed(&red, green: &green, blue: &blue, alpha: &alpha)
        return (red, green, blue, alpha)
    }
}