在 Swift 中,是否可以将字符串转换为枚举?

问题描述 投票:0回答:10

如果我有一个包含 a、b、c、d 情况的枚举,我可以将字符串“a”转换为枚举吗?

swift enums
10个回答
186
投票

当然。枚举可以有原始值。引用文档:

原始值可以是字符串、字符或任何整数或 浮点数类型

— 摘自:Apple Inc.“Swift 编程语言”。 iBooks。 https://itun.es/us/jEUH0.l

所以你可以使用这样的代码:

enum StringEnum: String 
{
    case one   = "value one"
    case two   = "value two"
    case three = "value three"
}

let anEnum = StringEnum(rawValue: "value one")!

print("anEnum = \"\(anEnum.rawValue)\"")

注意:不需要在每个case后面都写=“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"
}

48
投票

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

45
投票

您所需要的是:

enum Foo: String {
   case a, b, c, d
}

let a = Foo(rawValue: "a")
assert(a == Foo.a)

let 💩 = Foo(rawValue: "💩")
assert(💩 == nil)

21
投票

如果是 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
} 

10
投票

借鉴 djruss70 的答案来创建高度通用的解决方案:

extension CaseIterable {
    static func from(string: String) -> Self? { 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 开始,除了强力解决方案(switch 语句)之外,没有办法让它与 @objc 枚举一起工作。

如果有人碰巧知道一种方法可以使 @objc 枚举工作,我会对答案非常感兴趣。


3
投票

斯威夫特 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
    }
}

2
投票

扩展 Duncan 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)
    }
}

2
投票

对于 Int 枚举及其 String 表示形式,我声明枚举如下:

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

1
投票

我发现其他答案使这种方式变得更加复杂。这是一个快速简洁的示例。

enum Gender: String {
    case male, female, unspecified
}

简单枚举,请注意,我在枚举本身中添加了“: String”以将类型声明为字符串。

现在你所要做的就是:

let example: Gender = Gender(rawValue: "male")

就是这样,“example”现在是一个 Gender 类型的枚举,值为 .male

在 Swift 4+ 中您几乎不需要做任何其他事情。


0
投票

我用的是这个:

public enum Currency: CaseIterable, Codable {
    case AFN = 971 // Afghani (minor=2)
    case DZD = 012 // Algerian Dinar (minor=2)

...

    private static var cachedLookup: [String: Currency] = [:]
    
    init?(string: String) {
        if Self.cachedLookup.isEmpty {
            Self.cachedLookup = Dictionary(uniqueKeysWithValues: Self.allCases.map { ("\($0)", $0) })
        }
        
        if let currency = Self.cachedLookup[string] {
            self = currency
            return
        } else {
            return nil
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.