0

我正在尝试漂亮地打印(带有子对象的缩进)一个复合对象结构,其中父对象和每个子对象都确认 CustomDebugStringConvertible 协议。

到目前为止我的代码是:import Foundation

class StringUtils {
    static func appendIfValuePresent(key: String, value: AnyHashable?, toArray array: inout [String], separator: String = ": ") {
        if let value = value {
            array.append("\(key)\(separator)\(value)")
        }
    }
}

class Address: CustomDebugStringConvertible {
    var city: String? = "B'lore"
    var country: String? = "India"
    var pincode: String? = nil

    var debugDescription: String {
        var components = [String]()
        StringUtils.appendIfValuePresent(key: "city", value: city, toArray: &components)
        StringUtils.appendIfValuePresent(key: "country", value: country, toArray: &components)
        StringUtils.appendIfValuePresent(key: "pincode", value: pincode, toArray: &components)
        let debugStr = components.joined(separator: "\n")
        return debugStr
    }
}

class Contact: CustomDebugStringConvertible {
    var phNum: String? = "111-222-33"
    var email: String? = "ron@example.com"
    var address: Address? = Address()

    var debugDescription: String {
        var components = [String]()
        StringUtils.appendIfValuePresent(key: "phNum", value: phNum, toArray: &components)
        StringUtils.appendIfValuePresent(key: "email", value: email, toArray: &components)
        StringUtils.appendIfValuePresent(key: "address", value: address?.debugDescription, toArray: &components, separator: ":\n")
        let debugStr = components.joined(separator: "\n")
        return debugStr
    }
}

class Student: CustomDebugStringConvertible {
    var name = "ron"
    var contact: Contact? = Contact()
    var debugDescription: String {
        var components = [String]()
        StringUtils.appendIfValuePresent(key: "name", value: name, toArray: &components)
        StringUtils.appendIfValuePresent(key: "contact", value: contact?.debugDescription, toArray: &components, separator: ":\n")
        let debugStr = components.joined(separator: "\n")
        return debugStr
    }
}

let student = Student()

print(student)

上述代码片段的输出是:

// Actual output
/*
 name: ron
 contact:
 phNum: 111-222-33
 email: ron@example.com
 address:
 city: B'lore
 country: India
*/

但是,我想这样打印:

// Expected output
/*
 name: ron
 contact:
    phNum: 111-222-33
    email: ron@example.com
    address:
        city: B'lore
        country: India
*/

实现这一点的最佳方法是什么,保留代码的通用结构?

4

1 回答 1

0

我可以为我的问题设计一个解决方案并在此处发布解决方案:https ://gist.github.com/raunakp/16155d19d005939f1297b7c6cb6f890c

进口基金会

class StringUtils {
    static func appendIfValuePresent(key: String, value: AnyHashable?, toArray array: inout [String], separator: String = ": ") {
        if let value = value {
            array.append("\(key)\(separator)\(value)")
        }
    }
}

struct PrettyPrintableComponent {
    var indentationLevel = 0
    var indentationSeparator = "\t"
    var lineSeparator = "\n"
}

protocol HasPrettyPrintableComponent {
    var prettyPrintableComponent: PrettyPrintableComponent { get set }
}

protocol PrettyDebugPrintable: HasPrettyPrintableComponent, CustomDebugStringConvertible { }

extension PrettyDebugPrintable {
    var indentationLevel: Int {
        get { return prettyPrintableComponent.indentationLevel }
        set { prettyPrintableComponent.indentationLevel = newValue }
    }
    var indentationSeparator: String {
        get { return prettyPrintableComponent.indentationSeparator }
        set { prettyPrintableComponent.indentationSeparator = newValue }
    }
    var lineSeparator: String {
        get { return prettyPrintableComponent.lineSeparator }
        set { prettyPrintableComponent.lineSeparator = newValue }
    }
}

class Address: PrettyDebugPrintable {
    var city: String? = "B'lore"
    var country: String? = "India"
    var pincode: String? = nil

    var prettyPrintableComponent = PrettyPrintableComponent()

    var debugDescription: String {
        var components = [String]()
        StringUtils.appendIfValuePresent(key: "city", value: city, toArray: &components)
        StringUtils.appendIfValuePresent(key: "country", value: country, toArray: &components)
        StringUtils.appendIfValuePresent(key: "pincode", value: pincode, toArray: &components)
        let indentationSeparator = String.init(repeating: prettyPrintableComponent.indentationSeparator, count: prettyPrintableComponent.indentationLevel)
        let debugStr = indentationSeparator + components.joined(separator: prettyPrintableComponent.lineSeparator + indentationSeparator)
        return debugStr
    }
}

class Contact: PrettyDebugPrintable {
    var phNum: String? = "111-222-33"
    var email: String? = "ron@example.com"
    var address: Address? = Address()

    var prettyPrintableComponent = PrettyPrintableComponent()

    var debugDescription: String {
        var components = [String]()
        StringUtils.appendIfValuePresent(key: "phNum", value: phNum, toArray: &components)
        StringUtils.appendIfValuePresent(key: "email", value: email, toArray: &components)
        address?.prettyPrintableComponent.indentationLevel = self.prettyPrintableComponent.indentationLevel + 1
        StringUtils.appendIfValuePresent(key: "address", value: address?.debugDescription, toArray: &components, separator: ":\n")
        let indentationSeparator = String.init(repeating: prettyPrintableComponent.indentationSeparator, count: prettyPrintableComponent.indentationLevel)
        let debugStr = indentationSeparator + components.joined(separator: prettyPrintableComponent.lineSeparator + indentationSeparator)
        return debugStr
    }
}

class Student: PrettyDebugPrintable {
    var name = "ron"
    var contact: Contact? = Contact()

    var prettyPrintableComponent = PrettyPrintableComponent()

    var debugDescription: String {
        var components = [String]()
        StringUtils.appendIfValuePresent(key: "name", value: name, toArray: &components)
        contact?.prettyPrintableComponent.indentationLevel = self.prettyPrintableComponent.indentationLevel + 1
        StringUtils.appendIfValuePresent(key: "contact", value: contact?.debugDescription, toArray: &components, separator: ":\n")
        let indentationSeparator = String.init(repeating: prettyPrintableComponent.indentationSeparator, count: prettyPrintableComponent.indentationLevel)
        let debugStr = indentationSeparator + components.joined(separator: prettyPrintableComponent.lineSeparator + indentationSeparator)
        return debugStr
    }
}

let student = Student()

print(student)

// output
/*
name: ron
contact:
    phNum: 111-222-33
    email: ron@example.com
    address:
        city: B'lore
        country: India
*/
于 2019-07-21T06:11:11.090 回答