如何获取 Swift 枚举的默认字符串表示形式以进行进一步自定义
How to get the default string representation of a Swift enum for further customization
从 Swift 中的枚举开始:
enum UnitCode:UInt {
case Unknown = 0
case Hz = 1
case GPM = 2
case M3_Hour = 3
case mA = 4
case PSI = 5
case Bar = 6
}
对于其中的大多数,表达式如下:
let text = "\(aUnitCode)"
会产生一个不错的结果,因为打印形式与代码形式匹配(例如 .Hz == "Hz")。
但是对于 M3_Hour
,我想将其打印为 m³/hr
。所以符合CustomStringConvertable
,对吧?我认为以下行不通:
extension UnitCode: CustomStringConvertible {
var description:String {
return self == .M3_Hour ? "m³/hr" : String(describing: self)
}
}
没有。无限递归。认为这样。但是 Swift 经常让我感到惊讶(无论是好的还是坏的)。
如果枚举是 super/sub 类型关系,我将调用描述的“超级”版本来获取枚举的“默认”文本呈现。但是我不确定如何在我的错误分支中获得“枚举的默认字符串化”,以便我可以针对一个不同的值对其进行调整。有办法吗?
这对我有用,希望这是您所期望的。
enum UnitCode: UInt {
case Unknown = 0
case Hz = 1
case GPM = 2
case M3_Hour = 3
case mA = 4
case PSI = 5
case Bar = 6
}
let anUnit: UnitCode = .M3_Hour
extension UnitCode: CustomStringConvertible {
var description: String {
switch self {
case .M3_Hour:
return "m³/hr"
default:
return String(describing: self)
}
}
}
print(anUnit.self)
//m³/hr
我认为您实际代码的问题在于您在 CustomStringConvertible 实现中使用了 String(describing:)
。如果我们忽略 CustomStringConvertible 而只写一个自定义 属性,你可以做这样的事情:
enum UnitCode: UInt {
case Unknown = 0
case Hz = 1
case GPM = 2
case M3_Hour = 3
case mA = 4
case PSI = 5
case Bar = 6
var toString : String {
return self == .M3_Hour ? "m³/hr" : "\(self)"
}
}
我没有看到任何递归。 (不过我应该补充一点,我认为这很脆弱;我们所依赖的功能将来可能无法使用。Apple 可以随时更改对象的描述。)
但是 真实 答案是要么你应该使用 String 原始值而不是 Int 原始值,要么你应该提供一个 complete switch
所有案例,将每个案例与可用字符串相关联。
赞赏有关风格和解决方法的评论。我正在寻找的答案来自 Swift 论坛,非常简单:
Unfortunately, you can't. The function you'd need to call is internal
to the standard library.
所以基本上,当您不提供自己的 description
实现时,执行从枚举到编码字符串的后备转换的机制不可用。
(@matt 在评论中也说过,如果他回答了这个问题,我会为他巨大的声誉盈余加分)
从 Swift 中的枚举开始:
enum UnitCode:UInt {
case Unknown = 0
case Hz = 1
case GPM = 2
case M3_Hour = 3
case mA = 4
case PSI = 5
case Bar = 6
}
对于其中的大多数,表达式如下:
let text = "\(aUnitCode)"
会产生一个不错的结果,因为打印形式与代码形式匹配(例如 .Hz == "Hz")。
但是对于 M3_Hour
,我想将其打印为 m³/hr
。所以符合CustomStringConvertable
,对吧?我认为以下行不通:
extension UnitCode: CustomStringConvertible {
var description:String {
return self == .M3_Hour ? "m³/hr" : String(describing: self)
}
}
没有。无限递归。认为这样。但是 Swift 经常让我感到惊讶(无论是好的还是坏的)。
如果枚举是 super/sub 类型关系,我将调用描述的“超级”版本来获取枚举的“默认”文本呈现。但是我不确定如何在我的错误分支中获得“枚举的默认字符串化”,以便我可以针对一个不同的值对其进行调整。有办法吗?
这对我有用,希望这是您所期望的。
enum UnitCode: UInt {
case Unknown = 0
case Hz = 1
case GPM = 2
case M3_Hour = 3
case mA = 4
case PSI = 5
case Bar = 6
}
let anUnit: UnitCode = .M3_Hour
extension UnitCode: CustomStringConvertible {
var description: String {
switch self {
case .M3_Hour:
return "m³/hr"
default:
return String(describing: self)
}
}
}
print(anUnit.self)
//m³/hr
我认为您实际代码的问题在于您在 CustomStringConvertible 实现中使用了 String(describing:)
。如果我们忽略 CustomStringConvertible 而只写一个自定义 属性,你可以做这样的事情:
enum UnitCode: UInt {
case Unknown = 0
case Hz = 1
case GPM = 2
case M3_Hour = 3
case mA = 4
case PSI = 5
case Bar = 6
var toString : String {
return self == .M3_Hour ? "m³/hr" : "\(self)"
}
}
我没有看到任何递归。 (不过我应该补充一点,我认为这很脆弱;我们所依赖的功能将来可能无法使用。Apple 可以随时更改对象的描述。)
但是 真实 答案是要么你应该使用 String 原始值而不是 Int 原始值,要么你应该提供一个 complete switch
所有案例,将每个案例与可用字符串相关联。
赞赏有关风格和解决方法的评论。我正在寻找的答案来自 Swift 论坛,非常简单:
Unfortunately, you can't. The function you'd need to call is internal to the standard library.
所以基本上,当您不提供自己的 description
实现时,执行从枚举到编码字符串的后备转换的机制不可用。
(@matt 在评论中也说过,如果他回答了这个问题,我会为他巨大的声誉盈余加分)