¿Cómo puedo cambiar la representación textual que se muestra para un tipo en Swift?

91

¿Cómo puedo modificar la salida textual que se muestra en la interpolación de cadenas?

El Printableprotocolo parece el más obvio, pero se ignora tanto en la Interpolación de cadenas como al imprimir la instancia, por ejemplo:

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

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

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

Asimismo, la toString()convención tampoco tiene efecto:

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)

El comportamiento es diferente nuevamente en PlayGround, que usa su propia representación de cadena para estructuras, es decir:

p // {x 10, y 20}

¿Hay alguna forma de cambiar la forma en que se muestra una instancia?

mito
fuente
El código anterior funciona como se esperaría en Playgrounds en Xcode 6.3 beta 4
carbo18

Respuestas:

112

Rápido 2-4

Resumen

Cumplir con el CustomStringConvertibleprotocolo y agregar description:

var description: String {
    return "description here"
}

Ejemplo

Puedes crear algunas estructuras:

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

Si los inicializa:

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])

Las descripciones personalizadas aparecerán en su área de juegos:

ingrese la descripción de la imagen aquí

Consulte también CustomDebugStringConvertible, que puede utilizar para obtener resultados más detallados durante la depuración.


Nota de uso

Puede inicializar un Stringdesde cualquier tipo sin implementar este protocolo. Por ejemplo:

ingrese la descripción de la imagen aquí

Por esta razón, los docs dicen:

Por lo tanto, se desaconseja el uso CustomStringConvertiblecomo restricción genérica o el acceso descriptiondirecto a un tipo conforme .

Aaron Brager
fuente
37

Documentos relevantes de Apple Swift

Apple proporciona este ejemplo:

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

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

Si prueba esto en el patio de recreo, obtendrá el mismo problema que está obteniendo ( V11lldb_expr...). En el patio de recreo, obtienes la descripción en el lado derecho cuando llamas al inicializador, pero printlnno devuelve algo legible.

Sin embargo, fuera del patio de recreo, este código se comporta como era de esperar. Tanto su código como el código de muestra de Apple anterior imprimen lo correcto descriptioncuando se usan en un contexto que no es un patio de juegos.

No creo que puedas cambiar este comportamiento en el patio de recreo. También podría ser un error.

EDITAR : Estoy bastante seguro de que esto es un error; Envié un informe de error a Apple.

ACTUALIZACIÓN : En Swift 2, en lugar de Printable, use CustomStringConvertible( enlace de documento relevante ).

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

let value = MyType()
println("Created a \(value)")
// prints "Created a MyType: Untitled"
Cezary Wojcik
fuente
2

Esto parece ser un error en el patio de recreo. Si realmente compila y ejecuta el programa normalmente, imprime:

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

como se esperaba.

Debe informar esto en https://bugreport.apple.com

Nicolás H.
fuente
0

Si abre la vista de la consola: Ver -> Editor asistente -> Mostrar editor asistente, puede ver las líneas de impresión esperadas Verificado en xCode 6.3.2 con Yosimite 10.10

ingrese la descripción de la imagen aquí

Nikita Kurtin
fuente
0

Como alternativa en Swift 5+, puede extender String.StringInterpolation

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

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

Esto cambiará el valor de print("\(p)") pero no de print(p), que seguirá usando la descripción

Ryan Heitner
fuente
0

AppCodeproporciona un Generate| debugDescriptiony `` Generar | descripción`. Es mejor que escribirlos para una estructura con muchos miembros.

ingrese la descripción de la imagen aquí

javadba
fuente