1

I have an enum thats raw value is Int. I know How to get the raw value. But I am accessing the data through webservice and there data for Enum is coming in String value.

Let me show you my Enum, then we will discuss the data that need to be convert into Enum and then getting the raw value.

My Enum:

enum ReportStatus : Int {
case None = 0
case Received = 2
case Forward = 9
case Reporting = 14
case Completed = 50
}

and the data I am getting from webservice is sending me value in string like so

var valueToCompareWithEnum = "Forward"

what I want:

I want to match that string value and to get the resultant int value. For example as I am receiving "Forward" So I must convert it in enum and getting the 9 Int value.

I know I can make switch case for it but I wanted to know if it can be handled with more clean way.....

Thanks in advance please help.

4 Answers 4

3

You can let your enum implement CaseIterable and then compare your string to the string representation of each enum case using Array.first(where:)

enum ReportStatus : Int, CaseIterable {
    case None = 0
    case Received = 2
    case Forward = 9
    case Reporting = 14
    case Completed = 50

    static func translate(_ string: String) -> Int? {
        return ReportStatus.allCases.first(where: {string == "\($0)"})?.rawValue
    }
}

As a variant here is a global generic function that does the same but it returns the enum case rather than the raw value.

func translate<T: CaseIterable>(_ string: String, forEnum: T.Type) -> T? {
    return forEnum.allCases.first(where: {string == "\($0)"})
}

Usage

if let item = translate(valueToCompareWithEnum, forEnum: ReportStatus.self) {
    print(item.rawValue)
}
Sign up to request clarification or add additional context in comments.

Comments

2

You can code like this;

enum ReportStatus : Int {
    case None = 0
    case Received = 2
    case Forward = 9
    case Reporting = 14
    case Completed = 50

    static func getRawValue(from value : String) -> Int {
        switch value {
        case "Forward":
            return self.Forward.rawValue
        case "Received":
            return self.Received.rawValue
        case "Reporting":
            return self.Reporting.rawValue
        case "Completed":
            return self.Completed.rawValue
        default:
            return self.None.rawValue
        }
    }

}


var valueToCompareWithEnum = "Forward"

let myVal = ReportStatus.getRawValue(from: valueToCompareWithEnum)

print(myVal) // 9

6 Comments

there is no clean method other than this?
@A.s.ALI I guess .. YES.
Apple always frowned on the use of the word "get" in methods. Has that changed with Swift or maybe it just applies to properties?
@trojanfoe I always use get in my methods (both obj-c & swift) & I never faced any issue from the apple side. If you can give relevant link that will be more better to give you answer. I dont think Apple have any issue with this point.
@dahiya_boy It's built into Objective-C, for example if you declare a property @property (readonly) Thing* thing; you can implement that by providing - (Thing*)thing { ... }. That won't work with - (Thing*)getThing { ... }. I don't know about Swift however.
|
1

Since you're receiving these strings from a server, I assume you mean you're receiving them encoded in JSON. If so, then you likely want them to be Decodable. In that case, you can implement a custom decoder.

Before I show that, I'm going to rename your enum cases to match Swift style, which is a lowercase letter. I'm doing this to make the problem slightly harder and show more techniques you can use.

enum ReportStatus : Int {
    case none = 0
    case received = 2
    case forward = 9
    case reporting = 14
    case completed = 50
}

Here's the most straightforward approach:

extension ReportStatus: Decodable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let stringValue = try container.decode(String.self)

        switch stringValue {
        case "None": self = .none
        case "Received": self = .received
        case "Forward": self = .forward
        case "Reporting": self = .reporting
        case "Completed": self = .completed
        default:
            throw DecodingError
                .valueNotFound(Self.self,
                               .init(codingPath: decoder.codingPath,
                                     debugDescription: "Unknown value for report status: \(stringValue)"))

        }
    }
}

This is a very good technique, but since our case names do match the server's keys closely (just not perfectly), we could fix that up by lowercasing the key:

enum ReportStatus : Int, CaseIterable { // Note CaseIterable
    case none = 0
    case received = 2
    case forward = 9
    case reporting = 14
    case completed = 50
}

extension ReportStatus: Decodable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let stringValue = try container.decode(String.self)

        guard let value = Self.allCases.first(where: { String(describing: $0) == stringValue.lowercased() })
            else { throw DecodingError
                .valueNotFound(Self.self,
                               .init(codingPath: decoder.codingPath,
                                     debugDescription: "Unknown value for report status: \(stringValue)"))
        }
        self = value

    }
}

Comments

1

I recommend you switch Int enum to String to make it easer to parse and add one more field to get int value for each case:

enum ReportStatus: String {

    case none = "None"
    case received = "Received" 
    case forward = "Forward"
    case reporting = "Reporting"
    case completed = "Completed"

    var intValue: Int {
      switch self {
        case .none      : return 0 
        case .received  : return 2 
        case .forward   : return 9
        case .reporting : return 14
        case .completed : return 50
      }
   }
}


let valueToCompareWithEnum = "Forward"

if let myVal = ReportStatus(rawValue: valueToCompareWithEnum) {
    print(myVal.intValue) // 9
}

Because that data from web in String format it's kindly recommended parse it to String enum case and then use you'r own Int value where you need.

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.