Come posso modificare la rappresentazione testuale visualizzata per un tipo in Swift?


91

Come posso modificare l'output testuale che viene visualizzato nell'interpolazione di stringhe?

Il Printableprotocollo sembra il più ovvio ma viene ignorato sia nell'interpolazione di stringhe che durante la stampa dell'istanza, ad esempio:

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

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

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

Allo stesso modo la toString()convenzione non ha alcun effetto:

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)

Il comportamento è di nuovo diverso in PlayGround che utilizza la propria rappresentazione String per le strutture, ovvero:

p // {x 10, y 20}

C'è un modo per modificare la modalità di visualizzazione di un'istanza?


Il codice sopra funziona come ci si aspetterebbe in Playgrounds in Xcode 6.3 beta 4
carbo18

Risposte:


112

Swift 2-4

Sommario

Conformarsi al CustomStringConvertibleprotocollo e aggiungere description:

var description: String {
    return "description here"
}

Esempio

Puoi creare alcune strutture:

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

Se li inizializzi:

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

Le descrizioni personalizzate appariranno nel tuo playground:

inserisci qui la descrizione dell'immagine

Vedi anche CustomDebugStringConvertible, che puoi usare per un output più dettagliato durante il debug.


Nota sull'utilizzo

È possibile inizializzare un Stringda qualsiasi tipo senza implementare questo protocollo. Per esempio:

inserisci qui la descrizione dell'immagine

Per questo motivo, i documenti dicono:

L'uso CustomStringConvertiblecome vincolo generico o l'accesso descriptiondiretto a un tipo conforme è quindi sconsigliato.


37

Documenti Apple Swift pertinenti

Apple fornisce questo esempio:

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

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

Se lo provi in ​​playground, otterrai lo stesso problema che stai riscontrando ( V11lldb_expr...). In playground, ottieni la descrizione sul lato destro quando chiami l'inizializzatore, ma printlnnon restituisce qualcosa di leggibile.

Fuori dal campo di gioco, tuttavia, questo codice si comporta come ci si aspetterebbe. Sia il codice che il codice di esempio di Apple sopra riportato stampano il codice corretto descriptionse utilizzati in un contesto non di gioco.

Non credo che tu possa cambiare questo comportamento nel playground. Potrebbe anche essere solo un bug.

EDIT : Sono abbastanza sicuro che questo sia un bug; Ho inviato una segnalazione di bug ad Apple.

AGGIORNAMENTO : In Swift 2, invece di Printableutilizzare CustomStringConvertible( collegamento alla documentazione 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"

2

Sembra essere un bug nel parco giochi. Se effettivamente compili ed esegui il programma normalmente, stampa:

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

come previsto.

Dovresti segnalarlo su https://bugreport.apple.com


0

Se apri la vista della console: Visualizza -> Assistant Editor -> Mostra Assistant Editor puoi vedere le linee di stampa previste Controllato in xCode 6.3.2 con Yosimite 10.10

inserisci qui la descrizione dell'immagine


0

In alternativa in Swift 5+ puoi estendere String.StringInterpolation

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

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

Questo cambierà il valore per print("\(p)") ma non per print(p)- che continuerà a utilizzare la descrizione


0

AppCodefornisce un Generate| debugDescriptione `` Genera | descrizione ». È meglio digitarli per una struttura con molti membri.

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.