如何更改 Swift 中显示的类型的文本表示形式?

如何修改在字符串插值中显示的文本输出?

Printable协议看起来最明显,但是它在字符串插值和打印实例时都被忽略了,例如:

struct Point : Printable
{
var x = 0
var y = 0


var description : String {
return "(\(x), \(y))"
}


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

同样,toString()公约也没有效力:

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)

PlayGround 中的行为也不同,它使用自己的字符串表示结构,例如:

p // {x 10, y 20}

有没有办法可以更改实例的显示方式?

35843 次浏览

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"

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

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

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.

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

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

enter image description here