In Swift, is it possible to convert a string to an enum?

If I have an enum with the cases a,b,c,d is it possible for me to cast the string "a" as the enum?


Solution 1:

Sure. Enums can have a raw value. To quote the docs:

Raw values can be strings, characters, or any of the integer or floating-point number types

β€” Excerpt From: Apple Inc. β€œThe Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l,

So you can use code like this:

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

Note: You don't need to write = "one" etc. after each case. The default string values are the same as the case names so calling .rawValue will just return a string

EDIT

If you need the string value to contain things like spaces that are not valid as part of a case value then you need to explicitly set the string. So,

enum StringEnum: String 
{
  case one
  case two
  case three
}

let anEnum = StringEnum.one
print("anEnum = \"\(anEnum)\"")

gives

anEnum = "one"

But if you want case one to display "value one" you will need to provide the string values:

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

Solution 2:

All you need is:

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

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

let πŸ’© = Foo(rawValue: "πŸ’©")
assert(πŸ’© == nil)

Solution 3:

In Swift 4.2, the CaseIterable protocol can be used for an enum with rawValues, but the string should match against the enum case labels:

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 }
    }
}

usage:

print(MyCode.withLabel("one")) // Optional(MyCode.one)
print(MyCode(rawValue: "uno"))  // Optional(MyCode.one)

Solution 4:

In case with an enum with Int type you can do it so:

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
    }
}

And use:

let string = "Two"
if let item = MenuItem.enumFromString(string) {
    //in this case item = 1 
    //your code
}