如何使用UIColor值创建Swift枚举?

时间:2016-08-24 01:02:07

标签: swift enums

我正在制作一个绘图应用程序,我想通过使用枚举来引用我的颜色。例如,每次我想要那种红色时,使用Colors.RedColor而不是输入值会更干净,更方便。但是,Swift的原始值枚举似乎不接受UIColor作为一种类型。有没有办法用枚举或类似的方法做到这一点?

9 个答案:

答案 0 :(得分:44)

我是这样做的(基本上使用结构作为命名空间):

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

你用它就像:

UIColor.MyTheme.firstColor

因此,您可以在自定义主题中使用红色。

答案 1 :(得分:28)

如果您的颜色不是UIColor方便方法定义的颜色之一,则可以向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

答案 2 :(得分:15)

我使用计算属性来解决这个问题,这是我的代码

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

然后我可以像这样使用MyColor:

MyColor.navigationBarBackgroundColor.value

答案 3 :(得分:5)

  

如何使用UIColor值制作Swift枚举?

这就是你如何使用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

的帮助下

答案 4 :(得分:1)

实际上我使用这样的实现,因为有两个原因对我来说非常方便,第一个我可以使用dex值而另一个是常量中的所有颜色

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

用法

let backgroundGreyColor = ColorPalette.Gray.Medium.cgColor

答案 5 :(得分:1)

根据@ Jano的回答,我使用Int作为文字类型进行了改进:

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
}

优点是它不允许重复颜色(作为真正的枚举)并且我也支持alpha。

如您所见,您可以为不同的调色板/方案创建多个枚举。如果您希望视图能够使用任何调色板,您只需添加协议:

protocol Color {
    var color: UIColor { get }
}

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

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

这样你就可以拥有一个接受协议的函数:

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)

我还想做的是为方便起见添加静态变量:

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

给你一个更干净的api:

view.backgroundColor = MainPalette.brightRed

可以改进命名:你必须选择是否需要一个不错的便利api或为你的枚举命名。

答案 6 :(得分:0)

如果您想要返回多个值,请使用以下代码......绝对是  为我工作....

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

如何使用此代码    将.allvalues["index of your option"]传递到{0}位置以及UIColor为1位

String value

答案 7 :(得分:0)

这可以更加简洁(并且应该这样做):

extension UIColor
{
    static let myColor = UIColor(displayP3Red: 0.0, green: 0.7, blue: 0.0, alpha: 1.0)
}

(其他任何返回UIColor的方法同样适用,不需要displayP3Red

用法:

let someColor: UIColor = .myColor

答案 8 :(得分:0)

这个答案可能晚了,但是对于其他人来说发现这个问题。 我对上述答案不满意,因为将颜色添加为UIColors扩展并不总是您想要的,因为:

  1. 从软件体系结构的角度来看,它可能不是最佳解决方案。
  2. 您不能使用枚举所具有的功能,例如CaseIterable

这是我想出的解决方案:

enum PencilColor {
    case lightRed
    case darkPurple
    
    var associatedColor: UIColor {
        switch self {
        case .lightRed: return UIColor(red: 67/255, green: 173/255, blue: 247/255, alpha: 1.0)
        case .darkPurple: return UIColor(red: 67/255, green: 173/255, blue: 247/255, alpha: 1.0)
        }
    }
}