我有一个枚举,其原始值为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值。
我知道我可以为此制作开关盒,但是我想知道是否可以用更干净的方式来处理它。....
在此先感谢您的帮助。
答案 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)
}