Comment puis-je faire un Enum Swift avec la valeur UIColor?

je fais une application de dessin et je voudrais me référer à mes couleurs à travers l'utilisation d'un enum. Par exemple, il serait plus propre et plus pratique à utiliser Colors.RedColor au lieu de taper des valeurs à chaque fois que je veux cette couleur rouge. Cependant, les valeurs brutes de Swift ne semblent pas accepter UIColor en tant que type. Est-il un moyen de le faire avec un enum ou quelque chose de similaire?

18
demandé sur A Tyshka 2016-08-24 04:02:07

7 réponses

je fais comme ceci (en gros à l'aide d'une structure comme un espace de noms):

extension UIColor {
  struct MyTheme {
    static var firstColor: UIColor  { return UIColor(red: 1, green: 0, blue: 0, alpha: 1) }
    static var secondColor: UIColor { return UIColor(red: 0, green: 1, blue: 0, alpha: 1) }
  }
}

Et vous vous en servez de la forme:

UIColor.MyTheme.firstColor

ainsi vous pouvez avoir une couleur rouge à l'intérieur de votre thème personnalisé.

34
répondu FranMowinckel 2017-02-10 05:43:51

si votre couleur n'est pas celle définie par UIColor'méthode de convenance, vous pouvez ajouter une extension à UIColor:

extension UIColor {
    static var firstColor: UIColor  { return UIColor(red: 1, green: 0, blue: 0, alpha: 1) }
    static var secondColor: UIColor { return UIColor(red: 0, green: 1, blue: 0, alpha: 1) }
}

// Usage
let myColor = UIColor.firstColor
22
répondu Code Different 2017-02-10 05:39:58

j'utilise les propriétés calculées pour résoudre ce problème, c'est mon code

enum MyColor {
    case navigationBarBackgroundColor
    case navigationTintCololr
}

extension MyColor {
    var value: UIColor {
        get {
            switch self {
            case .navigationBarBackgroundColor:
                return UIColor(red: 67/255, green: 173/255, blue: 247/255, alpha: 1.0)
            case .navigationTintCololr:
                return UIColor.white
            }
        }
    }
}

alors je peux utiliser MyColor comme ceci:

MyColor.navigationBarBackgroundColor.value
11
répondu Teng 2016-11-11 09:32:40

Comment puis-je faire un Enum Swift avec une valeur UIColor?

voici comment vous feriez littéralement un enum avec une valeur UIColor:

import UIKit

final class Color: UIColor, RawRepresentable, ExpressibleByStringLiteral
{
    // MARK:- ExpressibleByStringLiteral

    typealias StringLiteralType = String

    convenience init(stringLiteral: String) {
        guard let (a,r,g,b) = Color.argb(hexColor: stringLiteral) else {
            assertionFailure("Invalid string")
            self.init(red: 0, green: 0, blue: 0, alpha: 0)
            return
        }
        self.init(red: r, green: g, blue: b, alpha: a)
    }

    // MARK:- RawRepresentable

    public typealias RawValue = String

    convenience init?(rawValue: RawValue) {
        guard let (a,r,g,b) = Color.argb(hexColor: rawValue) else { return nil }
        self.init(red: r, green: g, blue: b, alpha: a)
    }

    var rawValue: RawValue {
        return hexString()
    }

    // MARK:- Private

    /// Return color components in range [0,1] for hexadecimal color strings.
    /// - hexColor: case-insensitive string with format RGB, RRGGBB, or AARRGGBB.
    private static func argb(hexColor: String) -> (CGFloat,CGFloat,CGFloat,CGFloat)?
    {
        let hexAlphabet = "0123456789abcdefABCDEF"
        let hex = hexColor.trimmingCharacters(in: CharacterSet(charactersIn: hexAlphabet).inverted)
        var int = UInt32()
        Scanner(string: hex).scanHexInt32(&int)
        let a, r, g, b: UInt32
        switch hex.count {
        case 3: (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17) // RGB
        case 6: (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF) // RRGGBB
        case 8: (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF) // AARRGGBB
        default: return nil
        }
        return (CGFloat(a)/255, CGFloat(r)/255, CGFloat(g)/255, CGFloat(b)/255)
    }

    private func hexString() -> String {
        var red:   CGFloat = 0
        var green: CGFloat = 0
        var blue:  CGFloat = 0
        var alpha: CGFloat = 0
        if self.getRed(&red, green: &green, blue: &blue, alpha: &alpha) {
            return String(format: "#%02X%02X%02X%02X", UInt8(red * 255), UInt8(green * 255), UInt8(blue * 255), UInt8(alpha * 255))
        }
        assertionFailure("Invalid colour space.")
        return "#F00"
    }
}

enum Colors: Color {
    case red = "#F00"
//    case blue = "#F00" // Raw value for enum case is not unique
}

let color3 = Color(rawValue: "#000") // RGB
let color6 = Color(rawValue: "#123456") // RRGGBB
let color8 = Color(rawValue: "#12345678") // AARRGGBB
print(Colors(rawValue:"#F00") as Any) // red
print(Colors(rawValue:"#FF0000") as Any) // red
print(Colors(rawValue:"#FFFF0000") as Any) // red
print(Colors(rawValue:"#ABC") as Any) // nil because it’s not a member of the enumeration
// print(Colors(rawValue:"#XYZ") as Any) // assertion on debug, black on release
print(Colors.red) // red
print(Colors.red.rawValue) // UIExtendedSRGBColorSpace 1 0 0 1

Avec l'aide de

4
répondu Jano 2018-02-12 10:52:23

en fait j'utilise une telle implémentation, c'est très pratique pour moi à cause de deux raisons, d'abord je peux utiliser la valeur dex et une autre toutes les couleurs en constante

import UIKit

struct ColorPalette {
struct Gray {
    static let Light = UIColor(netHex: 0x595959)
    static let Medium = UIColor(netHex: 0x262626)
}
}

extension UIColor {
convenience init(red: Int, green: Int, blue: Int) {
    assert(red >= 0 && red <= 255, "Invalid red component")
    assert(green >= 0 && green <= 255, "Invalid green component")
    assert(blue >= 0 && blue <= 255, "Invalid blue component")

    self.init(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1.0)
}

convenience init(netHex: Int) {
    self.init(red: (netHex >> 16) & 0xff, green: (netHex >> 8) & 0xff, blue: netHex & 0xff)
}
}

utilisation

let backgroundGreyColor = ColorPalette.Gray.Medium.cgColor
1
répondu Aleksey Timoshchenko 2017-01-18 08:18:08

si vous voulez retourner plusieurs valeurs, utilisez le code ci-dessous... de travail pour moi....

enum GetDriverStatus : String {
    case ClockIn            = "Clock In"
    case TripStart          = "Trip Start"
    case BeaconTouchPlant   = "Beacon Touch Plant"
    case PickUp             = "Pick Up"
    case BeaconTouchSite    = "Beacon Touch Site"
    case BeaconLeftSite     = "Beacon Left Site"
    case DropOff            = "Drop Off"
    case BreakIn            = "Break In"
    case BreakOut           = "Break Out"
    case TripEnd            = "Trip End"
    case DayEnd             = "Day End"
    //case ClockOut           = "Clock Out"

    //Get data from ID
    static var allValues: [GetDriverStatus] {
        return [
            .ClockIn,
            .TripStart,
            .BeaconTouchPlant,
            .PickUp,
            .BeaconTouchSite,
            .BeaconLeftSite,
            .DropOff,
            .BreakIn,
            .BreakOut,
            .TripEnd,
            .DayEnd
        ]
    }

    //Get Color
    var colorAndStatus: (UIColor,String) {
        get {
            switch self {
            case .ClockIn,.TripStart: //Idle
                return (UIColor(red: 248/255, green: 39/255, blue: 71/255, alpha: 1.0),"Idle") //dark pink-red
            case .BeaconTouchPlant,.PickUp:
                return (UIColor(red: 46/255, green: 180/255, blue: 42/255, alpha: 1.0),"Picking up") //Green
            case .BeaconTouchSite:
                return (UIColor(red: 252/255, green: 172/255, blue: 0/255, alpha: 1.0),"On site") //orange
            case .DropOff,.BeaconLeftSite:
                return (UIColor(red: 12/255, green: 90/255, blue: 255/255, alpha: 1.0),"Dropping off") //blue
            case .BreakIn,.BreakOut:
                return (UIColor(red: 151/255, green: 151/255, blue: 151/255, alpha: 1.0),"On break") //warm-grey-two
            case .TripEnd:
                return (UIColor.black,"Trip end")
            case .DayEnd:
                return (UIColor.black,"Done for the day")
            }
        }
    }
} 

Comment utiliser ce code En passant .allvalues["index of your option"] vous UIColor à la position 0, ainsi que String value 1

GetDriverStatus.allValues[1].colorAndStatus.0 //UIColor.Black
GetDriverStatus.allValues[2].colorAndStatus.1 //"Picking up"
0
répondu kuldip bhalodiya 2017-12-20 11:31:38

basé sur la réponse de @Jano j'ai fait une amélioration en utilisant Int comme type littéral:

import UIKit

public final class Colors: UIColor {

}

extension Colors: ExpressibleByIntegerLiteral {
    public typealias IntegerLiteralType = Int

    public convenience init(integerLiteral value: Int) {
        let red = CGFloat((value & 0xFF0000FF) >> 24) / 0xFF
        let green = CGFloat((value & 0x00FF00FF) >> 16) / 0xFF
        let blue = CGFloat((value & 0x0000FFFF) >> 8) / 0xFF
        let alpha = CGFloat(value & 0x00FF00FF) / 0xFF

        self.init(red: red, green: green, blue: blue, alpha: alpha)
    }
}

extension Colors: RawRepresentable {
    public typealias RawValue = Int

    public var rawValue: RawValue {
        return hex
    }

    public convenience init?(rawValue: RawValue) {
        self.init(integerLiteral: rawValue)
    }
}

fileprivate extension UIColor {
    var hex: Int {
        var fRed: CGFloat = 0
        var fGreen: CGFloat = 0
        var fBlue: CGFloat = 0
        var fAlpha: CGFloat = 0
        if self.getRed(&fRed, green: &fGreen, blue: &fBlue, alpha: &fAlpha) {
            let red = Int(fRed * 255.0)
            let green = Int(fGreen * 255.0)
            let blue = Int(fBlue * 255.0)
            let alpha = Int(fAlpha * 255.0)
            let rgb = (alpha << 24) + (red << 16) + (green << 8) + blue
            return rgb
        } else {
            return 0x000000
        }
    }
}

public enum MainPalette: Colors {
    case red = 0xFF0000ff
    case white = 0xFFFFFFFF
}

public enum FeatureXPalette: Colors {
    case blue = 0x024F9Eff
//    case bluish = 0x024F9Eff // <- Can't do
    case red = 0xFF0000ff
}

l'avantage est qu'il n'autorise pas les couleurs dupliquées (en tant que véritable enum) et je supporte aussi alpha.

Comme vous pouvez le voir, vous pouvez créer plusieurs énumérations pour différentes palettes/schémas. Dans le cas où vous voulez que les vues puissent utiliser n'importe quelle palette, vous pouvez juste ajouter un protocole:

protocol Color {
    var color: UIColor { get }
}

extension MainPalette: Color {
    var color: UIColor {
        return rawValue
    }
}

extension FeatureXPalette: Color {
    var color: UIColor {
        return rawValue
    }
}

, de sorte que vous pouvez avoir une fonction qui prend en protocole:

func printColorEquality(color1: Color, color2: Color) {
    print(color1.color == color2.color)
}

let red1: Color = MainPalette.red
let red2: Color = FeatureXPalette.red

printColorEquality(color1: red1, color2: red2)

ce que j'aime aussi faire est d'ajouter des var statiques pour la commodité:

extension MainPalette {
    public static var brightRed: UIColor {
        return MainPalette.red.color
    }
}

qui vous donne une api plus propre:

view.backgroundColor = MainPalette.brightRed

la dénomination peut être améliorée: vous devez choisir si vous voulez une api de commodité agréable ou la dénomination agréable pour vos énums.

0
répondu Eric 2018-03-02 23:06:32