Как я могу изменить текстовое представление, отображаемое для типа в 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
carb18

Ответы:

112

Swift 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, что можно использовать для более подробного вывода во время отладки.


Примечание по использованию

Вы можете инициализировать a 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при использовании в контексте, не связанном с игровой площадкой.

Я не думаю, что вы можете изменить это поведение на детской площадке. Это также могло быть просто ошибкой.

РЕДАКТИРОВАТЬ : я почти уверен, что это ошибка; Я отправил в 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

Если вы откроете консоль: View -> Assistant Editor -> Show Assistant Editor, вы увидите ожидаемые строки печати. ​​Проверено в 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предоставляет Generate| debugDescriptionи «Создать | описание`. Лучше печатать их для структуры с большим количеством членов.

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

СтивенБош
источник