8

I want to convert SwiftUI view Color to UIKit UIcolor component. I have tried several ways and also refer the StackOverflow already given answers, But they did not work. It was also mentioned by some users in those posts. I have gone through the below code which is proposed by turingtested

but this is not working. Any suggestions or help is really appreciated.

fileprivate extension Color {
    func uiColor() -> UIColor {
        let components = self.components()
        return UIColor(red: components.r, green: components.g, blue: components.b, alpha: components.a)
    }
    private func components() -> (r: CGFloat, g: CGFloat, b: CGFloat, a: CGFloat) {
        let scanner = Scanner(string: self.description.trimmingCharacters(in: CharacterSet.alphanumerics.inverted))
        var hexNumber: UInt64 = 0
        var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0
        let result = scanner.scanHexInt64(&hexNumber)
        if result {
            r = CGFloat((hexNumber & 0xff000000) >> 24) / 255
            g = CGFloat((hexNumber & 0x00ff0000) >> 16) / 255
            b = CGFloat((hexNumber & 0x0000ff00) >> 8) / 255
            a = CGFloat(hexNumber & 0x000000ff) / 255
        }
    return (r, g, b, a)
    }
}
Mahmoud Adam
  • 5,772
  • 5
  • 41
  • 62
  • What exactly does “this is not working” mean? Does it not compile? Does it crash? Does it give wrong results? – Martin R Jan 10 '20 at 13:07
  • It works for `Colors` you declare like this: `Color(red: 0.74, green: 0.5, blue: 0.32)`, but not for static ones like `Color.red` – LuLuGaGa Jan 10 '20 at 13:13
  • 3
    That "solution" should never be used, it attempts to derive color components from the object's `description`... it can break at any moment. – Alladinian Jan 10 '20 at 13:51
  • I think self.description prints "red" for a Color.red – Chris Jun 18 '20 at 15:29

3 Answers3

31

If you are looking for an up-to-date answer:

From iOS 14 onward, the UIColor class has an initializer, which takes a SwiftUI color as argument: UIColor(Color.red).

mmi
  • 461
  • 6
  • 8
9

Basically, Apple doesn't intend for you to do this conversion. SwiftUI's Color is a View, and the design of the framework is that data flows to a View, which is then displayed. You are never supposed to extract data back from a View.

If you find yourself needing to use the components of a color, you should work with UIColor, and then convert to Color at the time you are ready to display it.

If you are trying to get the components of system colors like Color.red, I believe they are the same as the adaptive UIColor.systemRed, which does have accessible components.

Standard Colors documentation

John M.
  • 8,892
  • 4
  • 31
  • 42
  • 1
    Though I follow the logic, it's still so frustrating we can't just move away from UIColor. It seems heavily redundant. – TealShift Jul 21 '21 at 18:30
4

Update your answer to this to get rid of the long tuple warning and it works fine.

extension Color {
    func uiColor() -> UIColor {
        if #available(iOS 14.0, *) {
            return UIColor(self)
        }

        let scanner = Scanner(string: description.trimmingCharacters(in: CharacterSet.alphanumerics.inverted))
        var hexNumber: UInt64 = 0
        var r: CGFloat = 0.0, g: CGFloat = 0.0, b: CGFloat = 0.0, a: CGFloat = 0.0

        let result = scanner.scanHexInt64(&hexNumber)
        if result {
            r = CGFloat((hexNumber & 0xFF000000) >> 24) / 255
            g = CGFloat((hexNumber & 0x00FF0000) >> 16) / 255
            b = CGFloat((hexNumber & 0x0000FF00) >> 8) / 255
            a = CGFloat(hexNumber & 0x000000FF) / 255
        }
        return UIColor(red: r, green: g, blue: b, alpha: a)
    }
}
Stritt
  • 527
  • 7
  • 7