Свифт очень долго перечисляет один другой случай: как с этим бороться? - PullRequest
0 голосов
/ 12 ноября 2018

Я пытаюсь сделать перечисление из 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 и некоторых двойных имен (серый, серый) я не могу определить тип raw.Поэтому я добавил два длинных переключателя name и 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 голосов
/ 12 ноября 2018

Как уже отмечали другие, 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

Это не законченное или готовое к использованию решение каким-либо образом (одна очевидная вещь, которая отсутствует, это то, что она не 'не соответствует шестнадцатеричным значениям, в которых пропущен альфа-компонент или префикс «#»), но у вас есть идея ...

Тогда мы можем использовать его следующим образом:

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

0 голосов
/ 12 ноября 2018

Вы можете использовать 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 кодировка / декодирование по умолчанию будет иметь тип / 1013 * (здесь это String).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...