Como posso alterar a representação textual exibida para um tipo no Swift?

91

Como posso modificar a saída textual que é exibida na interpolação de string?

O Printableprotocolo parece o mais óbvio, mas é ignorado na Interpolação de String e ao imprimir a instância, por exemplo:

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

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

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

Da mesma forma, a toString()convenção também não tem efeito:

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)

O comportamento é diferente novamente em PlayGround, que usa sua própria representação String para estruturas, ou seja:

p // {x 10, y 20}

Existe uma maneira de alterar a forma como uma instância é exibida?

mito
fonte
O código acima funciona como seria de se esperar no Playgrounds no Xcode 6.3 beta 4
carbo18

Respostas:

112

Swift 2 - 4

Resumo

Cumpra o CustomStringConvertibleprotocolo e adicione description:

var description: String {
    return "description here"
}

Exemplo

Você pode criar algumas estruturas:

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 você inicializá-los:

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

As descrições personalizadas aparecerão em seu playground:

insira a descrição da imagem aqui

Veja também CustomDebugStringConvertible, que você pode usar para uma saída mais detalhada durante a depuração.


Nota de Uso

Você pode inicializar um Stringde qualquer tipo sem implementar este protocolo. Por exemplo:

insira a descrição da imagem aqui

Por esse motivo, os documentos dizem:

Usar CustomStringConvertiblecomo uma restrição genérica ou acessar um tipo em conformidade descriptiondiretamente é, portanto, desencorajado.

Aaron Brager
fonte
37

Documentos relevantes do Apple Swift

A Apple fornece este exemplo:

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 você tentar fazer isso no playground, terá o mesmo problema que está obtendo ( V11lldb_expr...). No playground, você obtém a descrição no lado direito quando chama o inicializador, mas o printlnnão retorna algo legível.

Fora do playground, no entanto, esse código se comporta conforme o esperado. Tanto seu código quanto o código de amostra da Apple acima imprimem o correto descriptionquando usado em um contexto fora do playground.

Eu não acho que você pode mudar esse comportamento no playground. Também pode ser apenas um bug.

EDIT : Tenho certeza de que isso é um bug; Enviei um relatório de bug para a Apple.

ATUALIZAR : No Swift 2, em vez de Printable, use CustomStringConvertible( link do 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
fonte
2

Isso parece ser um bug no playground. Se você realmente compilar e executar o programa normalmente, ele imprimirá:

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

como esperado.

Você deve relatar isso em https://bugreport.apple.com

Nicholas H.
fonte
0

Se você abrir a visualização do console: Exibir -> Editor Assistente -> Mostrar Editor Assistente, você pode ver as linhas de impressão esperadas. Verificado no xCode 6.3.2 com Yosimite 10.10

insira a descrição da imagem aqui

Nikita Kurtin
fonte
0

Como alternativa no Swift 5+, você pode estender o String.StringInterpolation

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

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

Isso mudará o valor de, print("\(p)") mas não para print(p)- que ainda usará a descrição

Ryan Heitner
fonte
0

AppCodefornece um Generate| debugDescriptione `` Gerar | descrição ». Melhor do que digitá-los para uma estrutura com muitos membros.

insira a descrição da imagem aqui

Javadba
fonte