如何获取 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 在评论中也说过,如果他回答了这个问题,我会为他巨大的声誉盈余加分)