Swift非常长的枚举与一个不同的情况:如何处理?

Swift非常长的枚举与一个不同的情况:如何处理?,swift,Swift,我尝试用HTML颜色制作enum。第一刻,我以为它会很好,很简单,但我撞到了墙。颜色可以定义为名称:moroon、gray、gray(相同值)或RGBA字符串#00000000。我的起点是: enum HTMLColor { case aliceblue case antiquewhite case aqua case aquamarine case azure //..... many, many names and at the end:

我尝试用HTML颜色制作enum。第一刻,我以为它会很好,很简单,但我撞到了墙。颜色可以定义为名称:
moroon
gray
gray
(相同值)或RGBA字符串
#00000000
。我的起点是:

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

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

    case custom(String)
}
嗯。由于last
custom
和一些双重名称(灰色、灰色),我无法定义原始类型。因此,我添加了两个长开关name和hextstring:

    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(来自string:string)
init(来自decoder:decoder)
。我想要

let azure = HTMLColor(from: "azure")
并且得到了
.azure

或:

并获得
.hexString(hexValue)
以将其用作:

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

对于这个特定的问题,
enum
可能不是一个好主意?

您可以使用
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
而言,默认编码/解码将采用/from
RawValue
类型(这里是
String
)。

您可以使用
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
而言,默认的编码/解码将采用/from
RawValue
类型(这里是
String
)。

正如其他人所指出的,
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)
    }

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

print(c1) // --> .white
print(c2) // --> .custom("#F2F2F2FF")
print(c3) // --> .black
本质上,我们遵循
ExpressibleByStringLiteral
,这意味着我们可以用字符串文本初始化枚举。然后在初始值设定项中,我们搜索名称和值以查找匹配项或返回一个
.custom

无论如何,它都不是一个完整的或生产就绪的解决方案(缺少的一件明显的事情是,它不匹配省略alpha组件或“#”前缀的十六进制值),但您知道了

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

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

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

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

最后,您甚至可以扩展对Int-literal初始化的支持(例如,您可以使用
让c:HTMLColor=0xf2ff
),或者使用类似于的工具处理所有代码重复,正如其他人所指出的,
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)
    }

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

print(c1) // --> .white
print(c2) // --> .custom("#F2F2F2FF")
print(c3) // --> .black
本质上,我们遵循
ExpressibleByStringLiteral
,这意味着我们可以用字符串文本初始化枚举。然后在初始值设定项中,我们搜索名称和值以查找匹配项或返回一个
.custom

无论如何,它都不是一个完整的或生产就绪的解决方案(缺少的一件明显的事情是,它不匹配省略alpha组件或“#”前缀的十六进制值),但您知道了

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

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

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

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

最后,您甚至可以扩展对Int-literal初始化的支持(例如,您可以使用
let c:HTMLColor=0xf2ff
),或者使用类似于的工具处理所有代码重复。虽然您可能可以获得枚举来完成您想要的操作,但我怀疑这不是您的最佳选择。我建议您看看作为Apple UI工具包一部分的UIColor。我不是说你应该使用它(因为我不知道你的应用程序的细节),而是看看它的API。它可能会给您一些关于如何设计枚举或类的想法。有关详细信息,请参阅。虽然您可能可以获得一个枚举来执行所需操作,但我怀疑这不是您的最佳选择。我建议您看看作为Apple UI工具包一部分的UIColor。我不是说你应该使用它(因为我不知道你的应用程序的细节),而是看看它的API。它可能会给您一些关于如何设计枚举或类的想法。请参阅了解详细信息。这与我尝试过的方法完全相同;事实上,enum似乎是一个错误的想法;)非常感谢。这与我尝试过的方法完全相同;事实上,enum似乎是一个错误的想法;)非常感谢。好啊我添加了静态let hexValues:[String:String]=[“aliceblue”:“#F0F8FFFF”,…]以具有十六进制值,动态var hexValues,这并不好,但可以工作。好的。我添加了静态let hexValues:[String:String]=[“aliceblue”:“#F0F8FFFF”,…]以具有十六进制值、动态var hexValues,这虽然不好,但很有效。