Swift enum 使用 String value 获取 Int Enum 的值



我有一个原始值是 Int 的枚举。我知道如何获取原始值。但是我正在通过网络服务访问数据,并且枚举的数据以字符串值的形式出现。

让我向您展示我的枚举,然后我们将讨论需要转换为 Enum 然后获取原始值的数据。

我的枚举:

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

我从网络服务获得的数据正在向我发送价值 像这样字符串

var valueToCompareWithEnum = "Forward"

我想要什么:

我想匹配该字符串值并获取生成的 int 值。 例如,当我收到"转发"时,所以我必须在枚举中转换它 并获取 9 Int 值。

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

提前感谢请帮忙。

您可以让枚举实现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)
}

你可以这样编码;

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

由于您从服务器接收这些字符串,因此我假设您的意思是接收以 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
}
}

我建议您将 Int 枚举切换到字符串以使其更容易解析,并再添加一个字段以获取每种情况的 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
}

由于来自 Web 的数据以字符串格式提供,因此建议将其解析为字符串枚举大小写,然后在需要的地方使用您自己的 Int 值。

最新更新