Is there a way to use tabs to evenly space out description strings in Swift?

前端 未结 2 1576
北海茫月
北海茫月 2021-01-15 04:21

Overriding the description variable of a custom class:

override var description : String {
        let mirrored_object = Mirror(reflecting: self)
        let         


        
2条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-15 04:30

    I wouldn't use tabs but use 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")
    }
    

    For a struct like

    struct Foo: CustomStringConvertible
    {
        let userID = 42
        let username = "Foo"
        let verylongpropertyname: String? = "Bar"
    }
    

    this produces

    userID               = 42
    username             = Foo
    verylongpropertyname = Optional("Bar")
    

    As for the "Optional" part, it's not as easy as totiG suggests because the value you get from the mirror is of type Any. See this question.

    Update

    I overlooked that you wanted to have a slightly different format.

    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)"
        }
    }
    

    produces

    userID =               42
    username =             Foo
    verylongpropertyname = Optional("Bar")
    

    Update 2

    To get rid of the "Optional" thing, please see my answer here.

    If you use (from said answer) unwrap() or unwrapUsingProtocol() in description like this:

    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")
    }
    

    this will produce

    userID =               42
    username =             Foo
    verylongpropertyname = Bar
    

提交回复
热议问题