Comment puis-je modifier la représentation textuelle affichée pour un type dans Swift?

91

Comment puis-je modifier la sortie textuelle qui s'affiche dans l'interpolation de chaîne?

Le Printableprotocole semble le plus évident mais il est ignoré à la fois dans l'interpolation de chaîne et lors de l'impression de l'instance, par exemple:

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

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

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

De même, la toString()convention n'a aucun effet non plus:

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)

Le comportement est encore différent dans PlayGround qui utilise sa propre représentation String pour les structures, c'est-à-dire:

p // {x 10, y 20}

Existe-t-il un moyen de modifier la façon dont une instance est affichée?

Mythz
la source
Le code ci-dessus fonctionne comme prévu dans Playgrounds dans Xcode 6.3 beta 4
carbo18

Réponses:

112

Swift 2-4

Résumé

Conformez-vous au CustomStringConvertibleprotocole et ajoutez description:

var description: String {
    return "description here"
}

Exemple

Vous pouvez créer des structures:

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 vous les initialisez:

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

Les descriptions personnalisées apparaîtront dans votre terrain de jeu:

entrez la description de l'image ici

Voir aussi CustomDebugStringConvertible, que vous pouvez utiliser pour une sortie plus détaillée pendant le débogage.


Note d'utilisation

Vous pouvez initialiser un à Stringpartir de n'importe quel type sans implémenter ce protocole. Par exemple:

entrez la description de l'image ici

Pour cette raison, les documents disent:

L'utilisation CustomStringConvertiblecomme contrainte générique, ou l'accès descriptiondirect à un type conforme , est donc déconseillée.

Aaron Brager
la source
37

Documents Apple Swift pertinents

Apple fournit cet exemple:

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 vous essayez ceci dans le terrain de jeu, vous obtiendrez le même problème que celui que vous rencontrez ( V11lldb_expr...). Dans la cour de récréation, vous obtenez la description sur le côté droit lorsque vous appelez l'initialiseur, mais printlnne renvoie rien de lisible.

Hors du terrain de jeu, cependant, ce code se comporte comme vous vous en doutez. Votre code et l'exemple de code d'Apple ci-dessus impriment le correct descriptionlorsqu'ils sont utilisés dans un contexte non-terrain de jeu.

Je ne pense pas que vous puissiez changer ce comportement dans la cour de récréation. Cela pourrait aussi être juste un bug.

EDIT : Je suis presque sûr que c'est un bug; J'ai soumis un rapport de bogue à Apple.

MISE À JOUR : Dans Swift 2, au lieu de Printable, utilisez CustomStringConvertible( lien vers la documentation pertinente ).

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
la source
2

Cela semble être un bug dans la cour de récréation. Si vous compilez et exécutez le programme normalement, il imprime:

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

comme prévu.

Vous devez le signaler sur https://bugreport.apple.com

Nicholas H.
la source
0

Si vous ouvrez la vue de la console: Affichage -> Assistant Editor -> Show Assistant Editor, vous pouvez voir les lignes d'impression attendues Checked in xCode 6.3.2 with Yosimite 10.10

entrez la description de l'image ici

Nikita Kurtin
la source
0

Comme alternative dans Swift 5+, vous pouvez étendre la chaîne.

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

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

Cela changera la valeur pour print("\(p)") mais pas pour print(p)- qui utilisera toujours la description

Ryan Heitner
la source
0

AppCodefournit un Generate| debugDescriptionet `` Generate | description ». Beats les taper pour une structure avec de nombreux membres.

entrez la description de l'image ici

Javadba
la source