斯威夫特很长的枚举,有一种不同的情况:如何处理?

时间:2018-11-12 13:10:33

标签: swift

我尝试用HTML颜色制作枚举。最初,我以为这会很好而且很简单,但是我碰壁了。颜色可以定义为名称:moroongraygrey(相同值)或RGBA字符串#00000000。我从以下开始:

enum HTMLColor {
    case aliceblue
    case antiquewhite
    case aqua
    case aquamarine
    case azure

    //..... many, many names and at the end:

    case custom(String)
}

好。由于最后的custom和一些重复的名称(灰色,灰色),我无法定义原始类型。因此,我添加了两个长开关名称和hexString:

    public var name:String {
        switch self {
        case .aliceblue: return  "aliceblue"
        case .antiquewhite: return  "antiquewhite"
        case .aqua: return  "aqua"
        case .aquamarine: return  "aquamarine"
        case .azure: return  "azure"

        //..... many, many names and at the end:

        case .custom(let string): return string
        }
    }

与hexString类似–但是我可以用"#00000000"代替名称。

但是现在我还不知道如何实现init(from string:String)init(from decoder:Decoder)。我想拥有

let azure = HTMLColor(from: "azure")

得到.azure

或:

let custom = HTMLColor(from: "#AB0023FF")

并获得.hexString(hexValue)用作:

switch color {
    case .custom(let string): makeRealColorFromString(string)
    default: makeRealColorFromString(color.hexString)
}

对于这个特定的问题,也许enum并不是一个好主意吗?

2 个答案:

答案 0 :(得分:2)

您可以为此使用struct。像这样:

struct HTMLColor: RawRepresentable, Codable {
    typealias RawValue = String
    var rawValue: String
}

然后您可以在任何需要的地方以及任何需要的地方添加颜色保护套:

extension HTMLColor {
    static let aliceblue = HTMLColor(rawValue: "aliceblue")
    static let antiquewhite = HTMLColor(rawValue: "antiquewhite")
    static let aqua = HTMLColor(rawValue: "aqua")
    static let aquamarine = HTMLColor(rawValue: "aquamarine")
    static let azure = HTMLColor(rawValue: "azure")

    //..... many, many names, and even:

    static let customBlack = HTMLColor(rawValue: "#00000000")
}

现在您可以在代码中的任何位置使用HTMLColor.azure或执行let custom = HTMLColor(rawValue: "#AB0023FF")

对于RawRepresentable,默认编码/解码应为RawValue类型(或为String类型)。

答案 1 :(得分:0)

正如其他人指出的那样,enum(尽管直觉表明如此)可能不是实现此目的的最佳选择。话虽如此,如果您要做要使用一个枚举,则可以执行以下操作:

enum HTMLColor: CaseIterable, ExpressibleByStringLiteral {
    case white
    case black
    // ... others
    case custom(String)

    static var allCases: [HTMLColor] {
        return [.white, .black] // All except .custom here
    }

    var name: String {
        switch self {
        case .white: return  "white"
        case .black: return  "black"
        // ... others
        case .custom(let string): return string
        }
    }

    var hexString: String {
        switch self {
        case .white: return  "#FFFFFFFF"
        case .black: return  "#00000000"
        // ... others
        case .custom(let string): return string
        }
    }

    init(stringLiteral: String) {
        self = HTMLColor.allCases.first(where: { ($0.name == stringLiteral) || ($0.hexString == stringLiteral) }) ?? .custom(stringLiteral)
    }

}

从本质上讲,我们遵守ExpressibleByStringLiteral,这意味着我们可以用字符串文字初始化我们的枚举。然后,在初始化程序中,我们搜索名称和hexValues以查找匹配项或返回.custom

无论如何,这都不是一个完整的解决方案,也不是可用于生产的解决方案(一个明显的不足是,它与省略了alpha分量或'#'前缀的十六进制值不匹配),但是您明白了。 ..

然后我们可以像这样使用它:

let c1: HTMLColor = "#FFFFFFFF"
let c2: HTMLColor = "#F2F2F2FF"
let c3: HTMLColor = "black"

print(c1) // --> .white
print(c2) // --> .custom("#F2F2F2FF")
print(c3) // --> .black

最后,您甚至可以扩展对Int文字初始化的支持(例如,可以执行let c: HTMLColor = 0xF2F2F2FF)或使用Sourcery

之类的工具来处理所有代码重复