Swift 4中如何让Optional<X>打印包含Optional的完整描述?
获取Swift可选值的完整枚举描述
你说得没错,Swift的可选值底层确实是Optional<Wrapped>枚举,但默认的字符串表示会隐藏这些细节。要拿到像Optional.none或Optional.some(99)这种完整描述,有几个简单的方法:
方法1:使用反射API String(reflecting:)
Swift的反射机制可以帮我们获取值的完整“调试描述”,这也是XCTest在失败信息里用到的方式之一。直接把可选值传给String(reflecting:)就能得到你想要的结果:
let longFormDefinedOptionalInt: Optional<Int> = nil let shortFormDefinedOptionalInt: Int? = 99 print(String(reflecting: longFormDefinedOptionalInt)) // 输出 "Optional<Int>.none" print(String(reflecting: shortFormDefinedOptionalInt)) // 输出 "Optional<Int>.some(99)"
如果觉得<Int>类型标注有点冗余,你也可以自己处理字符串去掉类型部分,但默认的反射输出已经完全符合“真实描述”的需求了。
方法2:手动匹配Optional枚举的case
既然Optional本质是枚举,我们可以直接switch它的case,然后构造对应的字符串:
func fullOptionalDescription<T>(_ optional: T?) -> String { switch optional { case .none: return "Optional.none" case .some(let value): return "Optional.some(\(value))" } } print(fullOptionalDescription(longFormDefinedOptionalInt)) // 输出 "Optional.none" print(fullOptionalDescription(shortFormDefinedOptionalInt)) // 输出 "Optional.some(99)"
这个方法的好处是你可以完全自定义输出格式,比如改成和XCTest一致的Optional(99)风格,只需要调整返回的字符串即可。
补充:为什么默认print不显示完整枚举名?
这是因为Optional类型实现了CustomStringConvertible协议,它的description属性会返回简化后的结果:nil或者包裹的值。而反射用的是CustomDebugStringConvertible的debugDescription,或是直接通过反射拿到的完整元数据,所以能显示枚举的完整case名。
内容的提问来源于stack exchange,提问作者Oliver Pearmain
相关产品推荐
相关产品推荐

