web-dev-qa-db-fra.com

Comment obtenir des composants RVB à partir de Color SwiftUI

Si j'ai un SwiftUI Color:

let col: Color = Color(red: 0.5, green: 0.5, blue: 0.5)

Comment puis-je obtenir les composants RVB de col?
Comme ceci peut-être:

print(col.components.red)

Dans UIKit, je pouvais utiliser UIColor.getRed mais il ne semble pas y avoir d'équivalent dans SwiftUI.

10
Div

La réponse est non - il n'y a pas (encore) d'API, mais ...

La plupart des structures SwiftUI ont des champs qui sont private, comme dans Color.

Vous pouvez utiliser Mirror pour extraire de telles informations - mais gardez à l'esprit que ce n'est pas efficace.

Voici comment extraire la représentation hexadécimale d'un SwiftUI Color - à des fins éducatives.

Copiez et collez ceci dans une aire de jeux Xcode 11.

import UIKit
import SwiftUI

let systemColor = Color.red
let color = Color(red: 0.3, green: 0.5, blue: 1)

extension Color {

    var hexRepresentation: String? {
        let children = Mirror(reflecting: color).children
        let _provider = children.filter { $0.label == "provider" }.first
        guard let provider = _provider?.value else {
            return nil
        }
        let providerChildren = Mirror(reflecting: provider).children
        let _base = providerChildren.filter { $0.label == "base" }.first
        guard let base = _base?.value else {
            return nil
        }
        var baseValue: String = ""
        dump(base, to: &baseValue)
        guard let firstLine = baseValue.split(separator: "\n").first,
              let hexString = firstLine.split(separator: " ")[1] as Substring? else {
            return nil
        }
        return hexString.trimmingCharacters(in: .newlines)
    }

}

systemColor.hexRepresentation
color.hexRepresentation

Des couleurs comme .red, .white, etc., ne semblent pas contenir beaucoup d'informations lorsque dumped.

Juste leur nom de "système".

▿ red
  ▿ provider: SwiftUI.(unknown context at $1297483bc).ColorBox<SwiftUI.SystemColorType> #0
    - super: SwiftUI.(unknown context at $129748300).AnyColorBox
    - base: SwiftUI.SystemColorType.red

Un Color instancié avec des composants red/blue/green le fait à la place.

▿ #4C80FFFF
  ▿ provider: SwiftUI.(unknown context at $11cd2e3bc).ColorBox<SwiftUI.Color._Resolved> #0
    - super: SwiftUI.(unknown context at $11cd2e300).AnyColorBox
    ▿ base: #4C80FFFF
      - linearRed: 0.073238954
      - linearGreen: 0.21404114
      - linearBlue: 1.0
      - opacity: 1.0

Dans l'aire de jeux, vous verrez:

  • systemColor.hexRepresentation renvoyant nil
  • color.hexRepresentation retour "#4C80FFFF"
2
Matteo Pacini

En attente d'une API, j'ai abusé du protocole CustomStringConvertible pour le cas rgba simple où le format de description des couleurs est #rrggbbaa

debugPrint(Color.red)
debugPrint(Color(red: 1.0, green: 0.0, blue: 0.0))
debugPrint(Color(red: 1.0, green: 0.3, blue: 0.0))
debugPrint(Color(.sRGB, red: 1.0, green: 0.0, blue: 0.5, opacity: 0.3))
debugPrint(Color(hue: 1.0, saturation: 0.0, brightness: 1.0))
debugPrint(Color(.displayP3, red: 1.0, green: 0.0, blue: 0.0, opacity: 1.0).description)

red
#FF0000FF
#FF4C00FF
#FF00804D
#FFFFFFFF
"DisplayP3(red: 1.0, green: 0.0, blue: 0.0, opacity: 1.0)"

comme vous pouvez le voir, des choses comme Color.red vident simplement "rouge" mais si vous travaillez avec des couleurs RVB simples générées par du code (c'est-à-dire à partir d'un sélecteur de couleurs), ce n'est pas trop mal

extension SwiftUI.Color {
    var redComponent: Double? {
        let val = description
        guard val.hasPrefix("#") else { return nil }
        let r1 = val.index(val.startIndex, offsetBy: 1)
        let r2 = val.index(val.startIndex, offsetBy: 2)
        return Double(Int(val[r1...r2], radix: 16)!) / 255.0
    }

    var greenComponent: Double? {
        let val = description
        guard val.hasPrefix("#") else { return nil }
        let g1 = val.index(val.startIndex, offsetBy: 3)
        let g2 = val.index(val.startIndex, offsetBy: 4)
        return Double(Int(val[g1...g2], radix: 16)!) / 255.0
    }

    var blueComponent: Double? {
        let val = description
        guard val.hasPrefix("#") else { return nil }
        let b1 = val.index(val.startIndex, offsetBy: 5)
        let b2 = val.index(val.startIndex, offsetBy: 6)
        return Double(Int(val[b1...b2], radix: 16)!) / 255.0
    }

    var opacityComponent: Double? {
        let val = description
        guard val.hasPrefix("#") else { return nil }
        let b1 = val.index(val.startIndex, offsetBy: 7)
        let b2 = val.index(val.startIndex, offsetBy: 8)
        return Double(Int(val[b1...b2], radix: 16)!) / 255.0
    }
}
2
Nicola Ferruzzi