How can I make a Swift enum with UIColor value?

前端 未结 9 734
深忆病人
深忆病人 2020-12-16 09:37

I\'m making a drawing app and I would like to refer to my colors through use of an enum. For example, it would be cleaner and more convenient to use Colors.RedColor

9条回答
  •  野趣味
    野趣味 (楼主)
    2020-12-16 10:09

    How can I make a Swift enum with UIColor value?

    This is how you would literally make an enum with a UIColor value:

    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
    

    With help from

    • benhurott/UIColorExtension.md
    • Swift 3 UIColor utilities for random color and color from hex code
    • Raw type 'Bool' is not expressible by any literal

提交回复
热议问题