Я хотел бы иметь перечисление Int, которое также можно «сериализовать» как Int или String.
enum Fruits : Int {
case Banana = 1
case Apple = 123
}
let favorite = Frutis(fromRaw: 1)
let banana = Fruits(from: "Banana")
assert(favorite==banana)
assert(favorite.rawValue == 1)
assert(String(describing: favorite) == "Banana")
Как я могу сделать это без реализации init(fromRaw:) и init(from:) для всех случаев? Перечисление содержит много записей, и я хотел бы избежать раздутого кода.





Вы можете добавить его как вычисляемое свойство, например:
enum Fruits: Int {
case banana = 1
case apple = 123
var stringRepresentation: String {
return "\(self)"
}
}
Таким образом, вы можете использовать его вот так let favorite = Fruits.banana.stringRepresentation, и если вы хотите получить значение Int, просто вызовите .rawValue.
Если вы хотите получить значение перечисления из строки, я думаю, вам придется использовать что-то вроде init(from: ).
Это потребует записи всех возможных случаев, так что это не самый чистый код. Зависит от того, чего вы пытаетесь достичь, но, возможно, вам лучше использовать для этого Словарь.
Это работает всеми способами, кроме String -> Fruits. Кому я могу получить перечисление из строки?
Насколько мне известно, нет возможности сделать это динамически, и для этого потребуется выписать все возможные случаи.
Я не думаю, что есть способ сделать именно то, что вы хотите. То, что у меня есть ниже, - это способ сделать что-то подобное, но это займет некоторое время, если у вас много случаев.
enum Fruits : Int {
case Banana = 1
case Apple = 123
var stringValue: String {
return "\(self)"
}
init?(stringValue: String) {
switch stringValue {
case "Banana":
self.init(rawValue: 1)
case "Apple":
self.init(rawValue: 123)
default:
self.init(rawValue: 0)
}
}
}
let favorite = Fruits(rawValue: 1)
let banana = Fruits(stringValue: "Banana")
assert(favorite==banana)
assert(favorite?.rawValue == 1)
assert(favorite?.stringValue == "Banana")
Я собрал это из связанных ответов, которые поддерживают все преобразования.
enum Fruits : Int, CaseIterable {
case banana = 1
case apple = 123
init?<S: StringProtocol>(_ string: S) {
guard let value = Fruits.allCases.first(where: { "\($0)" == string }) else {
return nil
}
self = value
}
var stringRepresentation: String {
return "\(self)"
}
}
let favorite = Fruits(rawValue: 123)!
let apple = Fruits("apple")!
assert(favorite == apple)
assert(favorite.rawValue == 123)
assert(String(describing: favorite) == "apple")
Связанный вопрос: Как упростить enum custom init (может быть даже дубликат). Также имейте в виду, что соглашение об именах Swift для случаев перечисления — lowerCamelCase.