Bagaimana cara mengubah representasi tekstual yang ditampilkan untuk suatu tipe di Swift?

91

Bagaimana cara mengubah keluaran tekstual yang ditampilkan dalam interpolasi string?

The Printableprotokol terlihat paling jelas tapi itu diabaikan di kedua String interpolasi dan saat mencetak contoh, misalnya:

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

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

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

Demikian juga, toString()konvensi tidak berpengaruh baik:

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)

Perilakunya berbeda lagi di PlayGround yang menggunakan representasi String-nya sendiri untuk struct, yaitu:

p // {x 10, y 20}

Adakah cara agar saya dapat mengubah cara sebuah instance ditampilkan?

Mythz
sumber
Kode di atas berfungsi seperti yang diharapkan di Playgrounds di Xcode 6.3 beta 4
carbo18

Jawaban:

112

Cepat 2 - 4

Ringkasan

Sesuai dengan CustomStringConvertibleprotokol dan tambahkan description:

var description: String {
    return "description here"
}

Contoh

Anda dapat membuat beberapa struct:

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

Jika Anda menginisialisasi mereka:

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

Deskripsi khusus akan muncul di taman bermain Anda:

masukkan deskripsi gambar di sini

Lihat juga CustomDebugStringConvertible, yang dapat Anda gunakan untuk keluaran lebih panjang selama debugging.


Catatan Penggunaan

Anda dapat menginisialisasi Stringdari jenis apa pun tanpa menerapkan protokol ini. Sebagai contoh:

masukkan deskripsi gambar di sini

Untuk alasan ini, dokumen tersebut mengatakan:

Oleh karena itu, menggunakan CustomStringConvertiblesebagai batasan umum, atau mengakses tipe yang sesuai descriptionsecara langsung, tidak disarankan.

Aaron Brager
sumber
37

Dokumen Swift Apple yang relevan

Apple memberikan contoh ini:

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

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

Jika Anda mencoba ini di taman bermain, Anda akan mendapatkan masalah yang sama dengan yang Anda dapatkan ( V11lldb_expr...). Di taman bermain, Anda mendapatkan deskripsi di sisi kanan saat Anda memanggil penginisialisasi, tetapi printlntidak mengembalikan sesuatu yang terbaca.

Di luar taman bermain, bagaimanapun, kode ini berperilaku seperti yang Anda harapkan. Baik kode Anda maupun kode sampel dari Apple di atas mencetak yang benar descriptionsaat digunakan dalam konteks non-taman bermain.

Saya tidak berpikir Anda bisa mengubah perilaku ini di taman bermain. Bisa juga hanya bug.

EDIT : Saya cukup yakin bahwa ini adalah bug; Saya mengirimkan laporan bug ke Apple.

PEMBARUAN : Di Swift 2, alih-alih Printable, gunakan CustomStringConvertible( tautan dokumen yang relevan ).

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
sumber
2

Ini tampaknya menjadi bug di taman bermain. Jika Anda benar-benar mengkompilasi dan menjalankan program secara normal, ini akan mencetak:

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

seperti yang diharapkan.

Anda harus melaporkannya di https://bugreport.apple.com

Nicholas H.
sumber
0

Jika Anda membuka tampilan konsol: View -> Assistant Editor -> Show Assistant Editor Anda dapat melihat garis cetak yang diharapkan Diperiksa di xCode 6.3.2 dengan Yosimite 10.10

masukkan deskripsi gambar di sini

Nikita Kurtin
sumber
0

Sebagai alternatif di Swift 5+, Anda bisa memperluas String.StringInterpolation

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

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

Ini akan mengubah nilai untuk print("\(p)") tetapi tidak untuk print(p)- yang masih akan menggunakan deskripsi

Ryan Heitner
sumber
0

AppCodemenyediakan Generate| debugDescriptiondan `` Hasilkan | deskripsi`. Ketukan mengetik mereka untuk struct dengan banyak anggota.

masukkan deskripsi gambar di sini

StephenBoesch
sumber