我不会使用标签,而是使用padding(...):
var description : String {
let mirrored_object = Mirror(reflecting: self)
let childrenWithLabel = mirrored_object.children.filter { $0.label != nil }
let maxLen = childrenWithLabel.map { Int($0.label!.characters.count) }.max() ?? 0
let lines = childrenWithLabel.map { $0.label!.padding(toLength: maxLen, withPad: " ", startingAt: 0) + " = \($0.value)" }
return lines.joined(separator: "\n")
}
对于像这样的结构
struct Foo: CustomStringConvertible
{
let userID = 42
let username = "Foo"
let verylongpropertyname: String? = "Bar"
}
这会产生
userID = 42
username = Foo
verylongpropertyname = Optional("Bar")
至于“可选”部分,它并不像totiG 建议的那么简单,因为您从镜像中获得的值是Any 类型。见this question。
更新
我忽略了您想要稍微不同的格式。
var description : String {
let mirrored_object = Mirror(reflecting: self)
let childrenWithLabel = mirrored_object.children.filter { $0.label != nil }
let separator = " = "
let firstColumnWidth = (childrenWithLabel.map { Int($0.label!.characters.count) }.max() ?? 0) + separator.characters.count
let lines = childrenWithLabel.map {
($0.label! + separator).padding(toLength: firstColumnWidth, withPad: " ", startingAt: 0) + "\($0.value)"
}
}
生产
userID = 42
username = Foo
verylongpropertyname = Optional("Bar")
更新 2
要摆脱“可选”的东西,请参阅my answer here。
如果您在description 中使用(来自上述答案)unwrap() 或 unwrapUsingProtocol(),如下所示:
var description : String {
let mirrored_object = Mirror(reflecting: self)
let childrenWithLabel = mirrored_object.children.filter { $0.label != nil }
let separator = " = "
let firstColumnWidth = (childrenWithLabel.map { Int($0.label!.characters.count) }.max() ?? 0) + separator.characters.count
let lines = childrenWithLabel.map {
($0.label! + separator).padding(toLength: firstColumnWidth, withPad: " ", startingAt: 0) + "\(unwrap($0.value))"
}
return lines.joined(separator: "\n")
}
这会产生
userID = 42
username = Foo
verylongpropertyname = Bar