如何在Swift中嵌套调试输出?

时间:2017-04-11 04:22:17

标签: swift

假设我有一个像这样的对象:

class MyClass
{
   let a_number : Int?
   let a_string : String?
   let an_array_of_strings : Array<String>?
   let an_array_of_objs : Array<Any>?
}

我怎么能这样做,以便当我将这个对象打印到控制台时,z是这样缩进的:

MyClass
a_number            = 4
a_string            = "hello"
an_array_of_strings = ["str1",
                      "str2",
                      "str3"]
an_array_of_objs    = [MyClass
                      a_number            = 5
                      a_string            = "world"
                      an_array_of_strings = nil
                      an_array_of_objs    = nil]

1 个答案:

答案 0 :(得分:1)

我使用递归函数和缩进的累加器参数来做到这一点。它默认为没有缩进,并且在每次递归调用时增加第一列的宽度:

customObj.arrInt & customObj.objectSOC

此功能使用my answer to another question

中的func describe<T>(_ x: T, indent: String = "") -> String { let mirror = Mirror(reflecting: x) guard !mirror.children.isEmpty else { return x is String ? "\"\(x)\"" : "\(x)" } switch mirror.displayStyle! { case .tuple: let descriptions = mirror.children.map { describe(unwrap($0.value), indent: indent) } return "(" + descriptions.joined(separator: ",\n\(indent)") + ")" case .collection: let descriptions = mirror.children.map { describe(unwrap($0.value), indent: indent) } return "[" + descriptions.joined(separator: ",\n\(indent)") + "]" case .dictionary: let descriptions = mirror.children.map { (child: Mirror.Child) -> String in let entryMirrors = Array(Mirror(reflecting: unwrap(child.value)).children) return describe(unwrap(entryMirrors[0].value), indent: indent) + ": " + describe(unwrap(entryMirrors[1].value)) } return "[" + descriptions.joined(separator: ",\n\(indent)") + "]" case .set: let descriptions = mirror.children.map { describe(unwrap($0.value), indent: indent) } return "Set(" + descriptions.joined(separator: ",\n\(indent)") + ")" default: let childrenWithLabel = mirror.children.filter { $0.label != nil } let separator = " = " let firstColumnWidth = (childrenWithLabel.map { Int($0.label!.characters.count) }.max() ?? 0) + separator.characters.count let subindent = indent + String(repeating: " ", count: firstColumnWidth) let lines = childrenWithLabel.map { indent + ($0.label! + separator).padding(toLength: firstColumnWidth, withPad: " ", startingAt: 0) + describe(unwrap($0.value), indent: subindent) } return (["\(mirror.subjectType)"] + lines).joined(separator: "\n") } } 功能
unwrap(_:)

当像这样使用func unwrap<T>(_ any: T) -> Any { let mirror = Mirror(reflecting: any) guard mirror.displayStyle == .optional, let first = mirror.children.first else { return any } return first.value } 时(我使describe(_:)成为一个结构,所以我可以使用成员初始化器):

MyClass

然后输出

struct MyClass: CustomStringConvertible
{
    let a_number : Int?
    let a_string : String?
    let an_array_of_strings : Array<String>?
    let an_array_of_objs : Array<Any>?

    var description: String { return describe(self) }
}

print(MyClass(a_number: 4, a_string: "hello",
              an_array_of_strings: ["str1", "str2", "str3"],
              an_array_of_objs: [
                  MyClass(a_number: 5, a_string: "world",
                          an_array_of_strings: nil, an_array_of_objs: nil)]))

请注意,这仅使用您的具体示例和一些简单的添加进行测试。我对MyClass a_number = 4 a_string = "hello" an_array_of_strings = ["str1", "str2", "str3"] an_array_of_objs = [MyClass a_number = 5 a_string = "world" an_array_of_strings = nil an_array_of_objs = nil] 的强制展开也不满意,但在我的浅层测试中,这只发生在mirror.displayStyle为空时,前面的mirror.children所涵盖。如果有人对此进行更密切的调查,我会喜欢评论。我在guard的文档中找不到任何内容。

就像在my answer to your related question中一样,我混淆了Mirror应该在哪里。恰恰相反,这个时候,呃! :)