我尝试用HTML颜色制作枚举。最初,我以为这会很好而且很简单,但是我碰壁了。颜色可以定义为名称:moroon
,gray
,grey
(相同值)或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
并不是一个好主意吗?
答案 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