Dart 枚举原始值指定问题 及 原始值与枚举值转换问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dart 枚举原始值指定问题 及 原始值与枚举值转换问题相关的知识,希望对你有一定的参考价值。
参考技术A 最近在看尝试Flutter,在开发时打算用枚举标示5个常用的按键KeyCode,因为就值关系特定几个KeyCode,所以打算仅设定5个枚举值,并且指定其原始值为其int值。但是我发现没办法指定这个int值。Dart语言的枚举不支持指定原始值,比如下面这种方式:
这样一来,如果想使枚举值有一个比较大的原始值,就只能使用本文件中KeyCode这种方式。一般如下:
但是如果我只想用Brown到Pink颜色这几种颜色,并且其原始值在100以上呢?比如键盘KeyCode☹️就有好多。
另外Dart语言枚举值到原始值的转换,直接取其index即可:
但却不支持从int原始值转换为枚举值,比如下面这种方式:
但enum提供了一个values属性,比如上面枚举有:
Color.values是一个有序数组,其下标和该位置的Color枚举值的原始值相等。
所以,如果一个枚举满足:1. 从零开始,2. 各个值密集排布,(Dart肯定满足,因为没办法指定原始值),
则可以通过下面方式实现原始值到枚举值的转换:
参考: https://news.dartlang.org/2013/04/enum-proposal-for-dart.html
Swift枚举使用String值获取Int Enum的值
【中文标题】Swift枚举使用String值获取Int Enum的值【英文标题】:Swift enum getting value of Int Enum using String value 【发布时间】:2019-09-04 12:53:30 【问题描述】:我有一个原始值是 Int 的枚举。我知道如何获得原始价值。但是我正在通过 web 服务访问数据,并且 Enum 的数据以字符串值的形式出现。
让我给你看我的 Enum,然后我们将讨论需要转换为 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 值。
我知道我可以为它制作开关盒,但我想知道它是否可以用更干净的方式处理.....
提前谢谢请帮忙。
【问题讨论】:
【参考方案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)
【讨论】:
【参考方案2】:你可以这样编码;
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
【讨论】:
除此之外没有干净的方法吗? @A.s.ALI 我猜.. 是的。 Apple 总是不赞成在方法中使用“get”这个词。 Swift 是否改变了这一点,或者它只适用于属性? @***foe 我总是在我的方法中使用 get (包括 obj-c 和 swift),而且我从来没有遇到过苹果方面的任何问题。如果您可以提供相关链接,那将更好地给您答案。我认为 Apple 在这一点上没有任何问题。 @dahiya_boy 它内置在 Objective-C 中,例如,如果您声明一个属性@property (readonly) Thing* thing;
,您可以通过提供 - (Thing*)thing ...
来实现它。这不适用于- (Thing*)getThing ...
。不过我不知道 Swift。【参考方案3】:
由于您是从服务器接收这些字符串,我假设您的意思是您正在接收以 JSON 编码的它们。如果是这样,那么您可能希望它们是可解码的。在这种情况下,您可以实现自定义解码器。
在我展示之前,我将重命名你的枚举 case 以匹配 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
【讨论】:
【参考方案4】:我建议您将 Int enum 切换为 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
因为来自网络的数据是字符串格式,所以建议将其解析为字符串枚举大小写,然后在需要的地方使用您自己的 Int 值。
【讨论】:
以上是关于Dart 枚举原始值指定问题 及 原始值与枚举值转换问题的主要内容,如果未能解决你的问题,请参考以下文章
带有浮点原始值的 Swift 枚举的“枚举大小写的原始值不是唯一的”