0

I'd like to have an Int enum which can be "serialized" as Int or String as well.

enum Fruits : Int {
   case Banana = 1
   case Apple = 123
}

let favorite = Frutis(fromRaw: 1)
let banana = Fruits(from: "Banana")
assert(favorite==banana)
assert(favorite.rawValue == 1)
assert(String(describing: favorite) == "Banana")

How can I do that without implementing init(fromRaw:) and init(from:) myself for all the cases? The enum contains many entries and I'd like to avoid a bloated code.

1
  • 1
    Related question: How to simplify enum custom init (might even be a duplicate). Also bear in mind that the Swift naming convention for enum cases is lowerCamelCase. Commented Apr 4, 2019 at 16:01

3 Answers 3

2

I put this together from the linked answers which supports all conversions.

enum Fruits : Int, CaseIterable {
    case banana = 1
    case apple = 123

    init?<S: StringProtocol>(_ string: S) {
        guard let value = Fruits.allCases.first(where: { "\($0)" == string }) else {
            return nil
        }
        self = value
    }
    var stringRepresentation: String {
        return "\(self)"
    }
}

let favorite = Fruits(rawValue: 123)!
let apple = Fruits("apple")!
assert(favorite == apple)
assert(favorite.rawValue == 123)
assert(String(describing: favorite) == "apple")
Sign up to request clarification or add additional context in comments.

Comments

1

You could add it as computed property, like this:

enum Fruits: Int {
    case banana = 1
    case apple = 123

    var stringRepresentation: String {
        return "\(self)"
    }
}

This way you can use it like this let favorite = Fruits.banana.stringRepresentation, and if you'd want to get the Int value you'd just call .rawValue.

If you'd want to get an enum value from a string I think you'll have to use something like init(from: ).

This will require writing out all possible cases, so it isn't the cleanest code. Depends on what you're trying to accomplish but maybe you could better use a Dictionary for this.

2 Comments

This works all ways except String -> Fruits. Who to I get the enum from a String?
As far as I know, there's no way to do this dynamically and this will require writing out all possible cases.
0

I don't think there is a way to do exactly what you want. What I've got below is a way to make something similar but it'll take a while to write out if you have a lot of cases.

enum Fruits : Int {
    case Banana = 1
    case Apple = 123

    var stringValue: String {
        return "\(self)"
    }

    init?(stringValue: String) {
        switch stringValue {
        case "Banana":
            self.init(rawValue: 1)
        case "Apple":
            self.init(rawValue: 123)
        default:
            self.init(rawValue: 0)
        }
    }
}

let favorite = Fruits(rawValue: 1)
let banana = Fruits(stringValue: "Banana")

assert(favorite==banana)
assert(favorite?.rawValue == 1)
assert(favorite?.stringValue == "Banana")

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.