Як я можу змінити текстове представлення, яке відображається для типу в Swift?


91

Як я можу змінити текстовий вивід, який відображається в інтерполяції рядків?

PrintableПротокол виглядає найбільш очевидні , але воно ігнорується в обох Струнної інтерполяції і при друку примірника, наприклад:

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

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

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

Аналогічно toString()Конвенція також не має ефекту:

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)

Поведінка знову відрізняється в PlayGround, яка використовує власне представлення String для структур, тобто:

p // {x 10, y 20}

Чи можу я змінити спосіб відображення екземпляра?


Вищезазначений код працює, як і слід було очікувати на Playgrounds у Xcode 6.3 beta 4
carbo18,

Відповіді:


112

Свіфт 2 - 4

Резюме

Відповідаємо CustomStringConvertibleпротоколу та додаємо description:

var description: String {
    return "description here"
}

Приклад

Ви можете створити деякі структури:

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

Якщо ви їх ініціалізуєте:

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

Спеціальні описи з’являться на вашому дитячому майданчику:

введіть тут опис зображення

Дивіться також CustomDebugStringConvertible, що ви можете використовувати для більш детального виводу під час налагодження.


Примітка щодо використання

Ви можете ініціалізувати Stringбудь-який тип, не застосовуючи цей протокол. Наприклад:

введіть тут опис зображення

З цієї причини в документації сказано:

Тому не рекомендується використовувати CustomStringConvertibleяк загальне обмеження або отримувати descriptionпрямий доступ до відповідного типу .


37

Відповідні документи Apple Swift

Apple наводить такий приклад:

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

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

Якщо ви спробуєте це на дитячому майданчику, ви отримаєте те саме питання, що і у вас ( V11lldb_expr...). На ігровому майданчику ви отримуєте опис праворуч, коли телефонуєте ініціалізатору, але printlnщось не читає.

Однак поза майданчиком цей код поводиться так, як ви очікували. Як ваш код, так і зразок коду від Apple, надруковані правильно, друкуються правильно, descriptionколи використовуються в неігровому контексті.

Я не думаю, що ви можете змінити цю поведінку на дитячому майданчику. Це також може бути просто помилка.

EDIT : Я майже впевнений, що це помилка; Я подав повідомлення про помилку в Apple.

ОНОВЛЕННЯ : У Swift 2 замість Printable, використовуйте CustomStringConvertible( відповідне посилання на документ ).

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

Здається, це помилка на дитячому майданчику. Якщо ви фактично скомпілюєте та запустите програму, вона друкує:

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

як і очікувалося.

Ви повинні повідомити про це на https://bugreport.apple.com


0

Якщо відкрити вигляд консолі: Перегляд -> Помічник редактора -> Показати помічник редактора, ви можете побачити очікувані рядки друку Перевірено в xCode 6.3.2 з Yosimite 10.10

введіть тут опис зображення


0

Як альтернативу в Swift 5+ ви можете розширити String.StringInterpolation

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

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

Це змінить значення для, print("\(p)") але не для print(p)- яке все одно використовуватиме опис


0

AppCodeзабезпечує a Generate| debugDescriptionта `` Generate | опис`. Beats, набираючи їх для структури зі багатьма учасниками.

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.