Если у меня есть перечисление с вариантами a, b, c, d, могу ли я указать строку «a» в качестве перечисления?
Ответы:
Конечно. Перечисления могут иметь необработанное значение. Чтобы процитировать документы:
Необработанные значения могут быть строками, символами или любыми целыми числами или числами с плавающей запятой.
- Отрывок из: Apple Inc. «Быстрый язык программирования». iBooks. https://itun.es/us/jEUH0.l ,
Итак, вы можете использовать такой код:
enum StringEnum: String
{
case one = "one"
case two = "two"
case three = "three"
}
let anEnum = StringEnum(rawValue: "one")!
print("anEnum = \"\(anEnum.rawValue)\"")
Примечание: вам не нужно писать = "one" и т. Д. После каждого случая. Строковые значения по умолчанию совпадают с именами случаев, поэтому вызов .rawValue
просто вернет строку
Если вам нужно, чтобы строковое значение содержало такие вещи, как пробелы, которые недопустимы как часть значения case, вам необходимо явно установить строку. Так,
enum StringEnum: String
{
case one
case two
case three
}
let anEnum = StringEnum.one
print("anEnum = \"\(anEnum)\"")
дает
anEnum = "один"
Но если вы хотите case
one
отобразить «значение один», вам нужно будет указать строковые значения:
enum StringEnum: String
{
case one = "value one"
case two = "value two"
case three = "value three"
}
Hashable
тип.
case one = "uno"
. Теперь, как разобрать "one"
значение enum? (нельзя использовать
= "one"
После каждого случая писать и т. Д. Не нужно . Строковые значения по умолчанию совпадают с именами случаев.
Все, что тебе нужно:
enum Foo: String {
case a, b, c, d
}
let a = Foo(rawValue: "a")
assert(a == Foo.a)
let 💩 = Foo(rawValue: "💩")
assert(💩 == nil)
В Swift 4.2 протокол CaseIterable можно использовать для перечисления с rawValues, но строка должна соответствовать меткам перечисления case:
enum MyCode : String, CaseIterable {
case one = "uno"
case two = "dos"
case three = "tres"
static func withLabel(_ label: String) -> MyCode? {
return self.allCases.first{ "\($0)" == label }
}
}
Применение:
print(MyCode.withLabel("one")) // Optional(MyCode.one)
print(MyCode(rawValue: "uno")) // Optional(MyCode.one)
В случае с перечислением с типом Int вы можете сделать это так:
enum MenuItem: Int {
case One = 0, Two, Three, Four, Five //... as much as needs
static func enumFromString(string:String) -> MenuItem? {
var i = 0
while let item = MenuItem(rawValue: i) {
if String(item) == string { return item }
i += 1
}
return nil
}
}
И используйте:
let string = "Two"
if let item = MenuItem.enumFromString(string) {
//in this case item = 1
//your code
}
enumFromString
метода для каждого используемого перечисления кажется безумием.
Расширение ответа Дункана C
extension StringEnum: StringLiteralConvertible {
init(stringLiteral value: String){
self.init(rawValue: value)!
}
init(extendedGraphemeClusterLiteral value: String) {
self.init(stringLiteral: value)
}
init(unicodeScalarLiteral value: String) {
self.init(stringLiteral: value)
}
}
Swift 4.2:
public enum PaymentPlatform: String, CaseIterable {
case visa = "Visa card"
case masterCard = "Master card"
case cod = "Cod"
var nameEnum: String {
return Mirror(reflecting: self).children.first?.label ?? String(describing: self)
}
func byName(name: String) -> PaymentPlatform {
return PaymentPlatform.allCases.first(where: {$0.nameEnum.elementsEqual(name)}) ?? .cod
}
}
Для Int enum и их строкового представления я объявляю enum следующим образом:
enum OrderState: Int16, CustomStringConvertible {
case waiting = 1
case inKitchen = 2
case ready = 3
var description: String {
switch self {
case .waiting:
return "Waiting"
case .inKitchen:
return "InKitchen"
case .ready:
return "Ready"
}
}
static func initialize(stringValue: String)-> OrderState? {
switch stringValue {
case OrderState.waiting.description:
return OrderState.waiting
case OrderState.inKitchen.description:
return OrderState.inKitchen
case OrderState.ready.description:
return OrderState.ready
default:
return nil
}
}
}
Применение:
order.orderState = OrderState.waiting.rawValue
let orderState = OrderState.init(rawValue: order.orderState)
let orderStateStr = orderState?.description ?? ""
print("orderStateStr = \(orderStateStr)")
Riffing на ответ djruss70 для создания обобщенного решения:
extension CaseIterable {
static func from(string: String) -> Self? {
return Self.allCases.first { string == "\($0)" }
}
func toString() -> String { "\(self)" }
}
Применение:
enum Chassis: CaseIterable {
case pieridae, oovidae
}
let chassis: Chassis = Chassis.from(string: "oovidae")!
let string: String = chassis.toString()
Примечание: это, к сожалению, не сработает, если перечисление объявлено @objc. Насколько я знаю, начиная с Swift 5.3, нет способа заставить это работать с перечислением @objc, кроме решений грубой силы (оператор switch).
Если кто-то знает, как сделать эту работу для перечислений @objc, мне будет очень интересен ответ.