Swift: Converting values to enumerations

Yesterday in #swift-lang, an enumeration discussion buzzed. A chat participant asked, “Is there any way to go backwards in an enum? I want to look up an enum based on a value.” The answer is simple and accessible. Creating enumerations from values returned by services and function represents an important touchpoint in Swift development.

RawRepresentable

The RawRepresentable protocol consists of two underlying functions: toRaw() and fromRaw(). These enable you to transform enumerations to and from underlying data states.

protocol RawRepresentable {
    typealias Raw
    class func fromRaw(raw: Raw) -> Self?
    func toRaw() -> Raw
}

For example, if you base your enumeration on integers, you can use the underlying sequence to move to and from that representation.

enum Nums : Int { 
    case Zero
    case One
    case Two
    case Three
}

var z : Nums = Nums.fromRaw(2)!
z == .Two // true
z == .Three // false

This example uses an Int raw-value type for its underlying representation. The type appears just after the name of the enumeration.

Fun with Raw Values

The enumeration values do not have to exactly match 0, 1, 2, etc. For example, you might assign arbitrary values to the enumeration entries.

enum Nums : Int {
    case Zero = 5
    case One = 30
    case Two = 15
    case Three = 20
}

var z : Nums = Nums.fromRaw(20)!
z == .Two // false
z == .Three // true
println(Nums.Three.toRaw()) // prints 20

Nor are your raw-convertible enumerations limited to integers. You have access to any equatable literal, specifically integer literals, floating-point literals, string literals, booleans, and nil. For example, you might use strings as raw values:

enum Lets : String {
    case X = "x"
    case Y = "y"
    case Z = "z"
}

var zz = Lets.fromRaw("z")
zz! == .Z // true
println(Lets.Y.toRaw())

Each case must declare a unique name and value. If you skip the value for integers, as in the first example in this post, they implicitly inherit their order. The count starts at zero and increases monotonically from there.

Raw vs Associated Values

Don’t confuse raw values with associated values. A raw value is constant across all uses of an enumeration. They are defined in the enumeration declaration at compile time. Associated values enable you to store typed information in an enumeration. These are defined at runtime.

enum CocoaResult {
    case success(NSObject) // associated success value
    case failure(NSError) // associated error value
}

2 Comments

  • var z : Nums = Nums.fromRaw(20)!

    has been changed to

    var z : Nums = Nums(rawValue: 20)!

    as of: Xcode V 6.1 (6A1052d)

    • Nice article and thank you DB Warner for that handy tip