Nerkyator
Nerkyator

Reputation: 3976

Get enum from value

I have a question about enum in Swift. I declared my enum like this:

enum FirstEnum : CustomStringConvertible {
    case VALUE1
    case VALUE2
    case VALUE3

    var description: String {
        switch self {
            case .VALUE1:
                return "First value"
            case .VALUE2:
                return "Second value"
            case .VALUE3:
                return "Third value"
        }
    }

    func getFromCode(value:String) -> FirstEnum? {
        switch value {
            case "v1":
                return FirstEnum.VALUE1
            case "v2":
                return FirstEnum.VALUE2
            case "v3" :
                return FirstEnum.VALUE3
        }
    }

I need to get enum from a string (like a dictionary) so I expect this line should work:

let foo = FirstEnum.getFromCode("v1") 

But XCode (7) expects a FirstEnum parameter for method getFromCode instead a String as declared in method definition, saying:

Cannot convert value of type "String" to expected argument type "FirstEnum"

Why this?...what I'm doing wrong?

Upvotes: 3

Views: 1004

Answers (3)

Arsen
Arsen

Reputation: 10951

Use Failable Initializers for Enumerations

You can use a failable initializer to select an appropriate enumeration member based on one or more parameters. The initializer can then fail if the provided parameters do not match an appropriate enumeration member.

The example below defines an enumeration called TemperatureUnit, with three possible states (Kelvin, Celsius, and Fahrenheit). A failable initializer is used to find an appropriate enumeration member for a Character value representing a temperature symbol:

enum TemperatureUnit {
    case Kelvin, Celsius, Fahrenheit
    init?(symbol: Character) {
        switch symbol {
        case "K":
            self = .Kelvin
        case "C":
            self = .Celsius
        case "F":
            self = .Fahrenheit
        default:
            return nil
        }
    }
}

Upvotes: 5

vacawama
vacawama

Reputation: 154513

You need a static func so that you can call it without an instance of the enum:

static func getFromCode(value:String) -> FirstEnum? {
    switch value {
    case "v1":
        return FirstEnum.VALUE1
    case "v2":
        return FirstEnum.VALUE2
    case "v3" :
        return FirstEnum.VALUE3
    default:
        return nil
    }
}

You were getting the error because there is a hidden parameter when calling a method that is the instance of the enum. Admittedly, the error message could be better.

Without static, you need an instance of the enum to call it. Note that this works with the function as you had it defined:

let foo = FirstEnum.VALUE3.getFromCode("v1")

Also, your switch needs to be exhaustive, which is why I added the default case.

Upvotes: 3

Adam
Adam

Reputation: 26907

In Swift, you can derive your enum from String.

enum FirstEnum : String {
    case VALUE1 = "First value"
    case VALUE2 = "Second value"
    case VALUE3 = "Third value"

    static func getFromCode(value:String) -> FirstEnum? {
        switch value {
        case "v1":
            return FirstEnum.VALUE1
        case "v2":
            return FirstEnum.VALUE2
        case "v3" :
            return FirstEnum.VALUE3
        default:
            return nil
        }
    }
}

Also, your getFromCode method should be static and needs a default clause.

But you don't need this method when you derive from String. To construct your enum value , you can use the rawValue like following:

let value = FirstEnum(rawValue: "First value")

Upvotes: 4

Related Questions