2016-08-24 2 views
17

Ich mache eine Zeichnung App und ich würde gerne auf meine Farben durch die Verwendung einer Enum beziehen. Zum Beispiel wäre es sauberer und bequemer, Colors.RedColor zu verwenden, anstatt Werte jedes Mal einzugeben, wenn ich diese rote Farbe haben möchte. Die Rohwert-Enums von Swift scheinen UIColor jedoch nicht als Typ zu akzeptieren. Gibt es eine Möglichkeit, dies mit einem Enum oder etwas Ähnlichem zu tun?Wie kann ich eine schnelle Enum mit UIColor Wert machen?

+0

"Swift's Rohwert-Enums scheinen UIColor jedoch nicht als Typ zu akzeptieren" Richtig. Eine Rohwertaufzählung kann nur einen String oder ein Zahlenliteral als Wert haben. – matt

Antwort

22

Ich mache es wie folgt aus (im Grunde eine Struktur als Namespace):

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) } 
    } 
} 

Und Sie verwenden Sie es wie:

UIColor.MyTheme.firstColor 

So können Sie eine rote Farbe in Ihrem eigenes Thema haben.

+0

Für mich ist das bei weitem die beste Lösung! – ixany

20

Wenn die Farbe nicht einer von denen, von UIColor ‚s bequemer Methode definiert ist, können Sie eine Erweiterung UIColor hinzufügen:

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 
+0

Und tatsächlich sind in Swift 3 die eingebauten Farben auch Klassenvariablen, so dass das passt. – matt

+0

Hier ist das Problem: Ich konnte 'static var red: UIColor' nicht tun, da UIColor bereits eine' red' Eigenschaft hat (In Swift 3). Ich könnte es etwas anderes wie 'redColor' nennen, aber dann scheint das eine schlechte Praxis zu sein, sowohl' red' als auch 'redColor' Eigenschaften –

+0

Dann nenne es nicht' rot', nenne es etwas anderes wie 'myRed' wenn deine Farbe ist nicht '# FF0000' –

9

I berechnete Eigenschaften verwenden, um dieses Problem zu lösen, das ist mein 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 
      } 
     } 
    } 
} 

dann kann ich MyColor wie folgt verwenden:

MyColor.navigationBarBackgroundColor.value 
1

Eigentlich benutze ich solche Implementierung ist es sehr bequem für mich, weil aus zwei Grund erste, den ich dex Wert und eine andere alle Farben in konstanten

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) 
} 
} 

Nutzung

let backgroundGreyColor = ColorPalette.Gray.Medium.cgColor 
0

verwenden können, wenn Sie möchten mehrere Werte zurückgeben und dann den folgenden Code verwenden ... es ist absolut funktioniert für mich ....

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") 
      } 
     } 
    } 
} 

Wie diesen Code verwenden .allvalues["index of your option"] Geben Sie UIColor bei 0 Position sowie String value als 1 Position

GetDriverStatus.allValues[1].colorAndStatus.0 //UIColor.Black 
GetDriverStatus.allValues[2].colorAndStatus.1 //"Picking up" 
2

Wie kann ich eine Swift-Enumeration mit UIColor Wert immer machen?

Dies ist, wie man buchstäblich eine Enumeration mit einem UIColor Wert machen würde:

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 = "abcdefABCDEF" 
     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 

Mit Hilfe von

0

@ Jano Antwort Basierend auf ich eine Verbesserung gemacht durch Int als wörtliche Art mit:

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 
} 

Der Vorteil ist, dass es keine doppelten Farben erlaubt (als echter Enum) und auch unterstütze ich alpha .

Wie Sie sehen, können Sie mehrere Enums für verschiedene Paletten/Schemen erstellen. Im Fall, dass Sie Ansichten jede Palette nutzen zu wollen in der Lage, können Sie fügen Sie einfach ein Protokoll:

protocol Color { 
    var color: UIColor { get } 
} 

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

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

so auf diese Weise eine Funktion haben kann, die in dem Protokoll nimmt:

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) 

Was Ich mag auch statische vars der Einfachheit halber ist hinzuzufügen tun:

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

, dass Sie eine sauberere api gibt:

view.backgroundColor = MainPalette.brightRed 

Die Benennung kann verbessert werden: Sie müssen wählen, ob Sie eine nette Annehmlichkeit api oder nette Benennung für Ihre enums wollen.

Verwandte Themen