How can I change the textual representation displayed for a type in Swift?

Swift

Swift Problem Overview


How can I modify the textual output that gets displayed in string interpolation?

The Printable protocol looks the most obvious but it's ignored in both String Interpolation and when printing the instance, e.g:

struct Point : Printable
{
    var x = 0
    var y = 0
    
    var description : String {
        return "(\(x), \(y))"
    }

    func toString() -> String {
        return description
    }
}

Likewise the toString() convention has no effect either:

var p = Point(x: 10, y: 20)

println(p)                   // V11lldb_expr_05Point (has 2 children)
println("\(p)")              // V11lldb_expr_05Point (has 2 children)
println(p.description)       // (10, 20)
println("\(p.description)")  // (10, 20)

The behavior is different again in PlayGround which uses its own String representation for structs, i.e:

p // {x 10, y 20}

Is there a way I can change how an instance is displayed?

Swift Solutions


Solution 1 - Swift

Swift 2 - 4

Summary

Conform to the CustomStringConvertible protocol and add description:

var description: String {
    return "description here"
}

Example

You can create some structs:

struct Animal : CustomStringConvertible {
    let type : String
    
    var description: String {
        return type
    }
}

struct Farm : CustomStringConvertible {
    let name : String
    let animals : [Animal]
    
    var description: String {
        return "\(name) is a \(self.dynamicType) with \(animals.count) animal(s)."
    }
}

If you initialize them:

let oldMajor = Animal(type: "Pig")
let boxer = Animal(type: "Horse")
let muriel = Animal(type: "Goat")

let orwellsFarm = Farm(name: "Animal Farm", animals: [oldMajor, boxer, muriel])

The custom descriptions will appear in your playground:

enter image description here

See also CustomDebugStringConvertible, which you can use for more verbose output during debugging.


Usage Note

You can initialize a String from any type without implementing this protocol. For example:

enter image description here

For this reason, the docs say:

> Using CustomStringConvertible as a generic constraint, or accessing a conforming type's description directly, is therefore discouraged.

Solution 2 - Swift

Relevant Apple Swift Docs

Apple provides this example:

struct MyType: Printable {
    var name = "Untitled"
    var description: String {
        return "MyType: \(name)"
    }
}
 
let value = MyType()
println("Created a \(value)")
// prints "Created a MyType: Untitled"

If you try this in playground, you will get the same issue that you're getting (V11lldb_expr...). In playground, you get the description on the right hand side when you call the initializer, but the println doesn't return something legible.

Out of playground, however, this code behaves as you would expect. Both your code and the sample code from Apple above print the correct description when used in a non-playground context.

I don't think you can change this behavior in playground. It could also just be a bug.

EDIT: I'm pretty sure that this is a bug; I submitted a bug report to Apple.

UPDATE: In Swift 2, instead of Printable, use CustomStringConvertible (relevant doc link).

struct MyType: CustomStringConvertible {
    var name = "Untitled"
    var description: String {
        return "MyType: \(name)"
    }
}

let value = MyType()
println("Created a \(value)")
// prints "Created a MyType: Untitled"

Solution 3 - Swift

This appears to be a bug in the playground. If you actually compile and run the programme normally it prints:

(10, 20)
(10, 20)
(10, 20)
(10, 20)

as expected.

You should report this at https://bugreport.apple.com

Solution 4 - Swift

As an alternative in Swift 5+ you can extend the String.StringInterpolation

struct Point {
    var x : Int
    var y : Int
}

extension String.StringInterpolation {
    mutating func appendInterpolation(_ value: Point) {
        appendInterpolation("\(value.x):\(value.y)")
    }
}

This will change the value for print("\(p)") but not for print(p) - which will still use the description

Solution 5 - Swift

for swift 5 just implement CustomStringConvertible (pls see https://developer.apple.com/documentation/swift/customstringconvertible/1539130-description)

Solution 6 - Swift

If you open the console view : View -> Assistant Editor -> Show Assistant Editor you can see expected print lines Checked in xCode 6.3.2 with Yosimite 10.10

enter image description here

Solution 7 - Swift

AppCode provides a Generate| debugDescription and ``Generate| description` . Beats typing them out for a struct with many members.

enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmythzView Question on Stackoverflow
Solution 1 - SwiftAaron BragerView Answer on Stackoverflow
Solution 2 - SwiftCezary WojcikView Answer on Stackoverflow
Solution 3 - SwiftNicholas H.View Answer on Stackoverflow
Solution 4 - SwiftRyan HeitnerView Answer on Stackoverflow
Solution 5 - SwiftRiddikView Answer on Stackoverflow
Solution 6 - SwiftNikita KurtinView Answer on Stackoverflow
Solution 7 - SwiftWestCoastProjectsView Answer on Stackoverflow