在 Swift 中,枚举是一等类型,可以给其添加计算属性,实例方法,构造函数,遵循协议,另外,还可以定义枚举来存储任意类型的关联值。这些特性可以让枚举适用于很多场合。
当我们需要打印日志,如何快速的将枚举值与其关联值一起转化成字符串呢?
当然我们可以让 enum 实现 CustomStringConvertible
等协议,然后实现各个 case 到 string 的转化。当 enum 的数量少时,还可以应付,当数量增加时,总得想想如何简化这个过程吧。
Mirror 的简介
Swift 中的反射机制是通过 Mirror 来实现的。我们可以给一个具体的 subject
(类、枚举、结构体、数字、闭包等所有的 Any 类型)创建一个 Mirror,然后通过 Mirror 来观察这个 subject
。
因此,可以通过 Mirror 获取到枚举的关联值的信息,简化将枚举转成字符串的过程,又不丢失枚举的关联值的信息。
Mirror 最简单的构造器为:
public init(reflecting subject: Any)
Mirror 提供了几个属性来告诉我们想查询的信息:
- displayStyle:类型为
DisplayStyle
enum,说明对象的展示类型,如:Struct、Class、Enum 等。 - children: 类型为
public typealias Child = (label: String?, value: Any)
的数组,其中,label
表示子节点的名称,value
表示子节点的值。 - subjectType:类型为
Any.Type
,说明对象的类型。
利用 Mirror 将枚举快速的转成字符串
假如有如下一个 enum:
enum TestEnum {
case null
case string(String)
case tuple(String, String)
}
接下里给 TestEnum 添加一个扩展
extension TestEnum {
public var label: String {
let mirror = Mirror(reflecting: self)
if let associated = mirror.children.first {
let valuesMirror = Mirror(reflecting: associated.value)
if !valuesMirror.children.isEmpty {
let parameters = valuesMirror.children.map { ".\($0.value)" }.joined(separator: ",")
return ".\(associated.label ?? "")(\(parameters))"
}
return ".\(associated.label ?? "")(.\(associated.value))"
}
return ".\(self)"
}
}
这样,就可以通过 label
属性获取到枚举值与其关联值转成的字符串:
TestEnum.null.label
TestEnum.string("Hello").label
TestEnum.tuple("Hello", "world").label
参考
- 有关 Mirror 的详细介绍,可以参考 Swift 反射 API 及用法。
label
方法的实现,为本人在看 Hero 源码时学习到的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)