Swift枚举使用字符串值获取Int Enum的值

时间:2019-09-04 12:53:30

标签: swift

我有一个枚举,其原始值为Int。我知道如何获得原始价值。但是我正在通过Web服务访问数据,并且Enum的数据以String值传入。

让我告诉我我的Enum,然后我们将讨论需要转换为Enum并获取原始值的数据。

我的枚举:

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

并且我从Web服务获取的数据为我带来了价值   像这样的字符串

var valueToCompareWithEnum = "Forward"

我想要的东西:

  

我想匹配该字符串值并获取结果int值。   例如,当我收到“转发”时,我必须将其转换为枚举   并获得9 Int值。

我知道我可以为此制作开关盒,但是我想知道是否可以用更干净的方式来处理它。....

在此先感谢您的帮助。

4 个答案:

答案 0 :(得分:1)

您可以像这样编码;

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

答案 1 :(得分:1)

我建议您将Int枚举切换为String,以使其易于解析,并再添加一个字段以获取每种情况的int值:

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
}

由于来自网络的数据为String格式,因此建议将其解析为String枚举大小写,然后在需要的地方使用您自己的Int值。

答案 2 :(得分:1)

由于您是从服务器接收这些字符串的,因此我假设您的意思是您正在接收以JSON编码的字符串。如果是这样,那么您可能希望它们可分解。在这种情况下,您可以实现自定义解码器。

在显示之前,我将重命名您的枚举大小写以匹配Swift样式,这是小写字母。我这样做是为了使问题更加棘手,并展示更多可以使用的技术。

enum ReportStatus : Int {
    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)

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

        }
    }
}

这是一种非常好的技术,但是由于我们的案例名称确实与服务器的密钥非常匹配(只是不完全匹配),因此我们可以通过减小密钥的大小来解决该问题:

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

    }
}

答案 3 :(得分:1)

您可以让您的枚举实现CaseIterable,然后使用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
    }
}

这是一个变体,它是一个全局通用函数,其功能相同,但它返回枚举大小写而不是原始值。

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

用法

if let item = translate(valueToCompareWithEnum, forEnum: ReportStatus.self) {
    print(item.rawValue)
}