用于字符串插值的Swift协议

14

我需要在Swift中的字符串插值中控制对象表示方式时实现哪个协议?

我想要指定类似于这样的输出中打印的内容:

struct A{

}

var a = A()
println("\(a)")
3个回答

25

您需要实现Printable协议:

该协议适用于希望自定义其文本表示的类型。当对象被写入OutputStreamType时,将使用此文本表示。

protocol Printable {
    var description: String { get }
}

当仅用于调试目的时,还有DebugPrintable协议:

此协议应由希望自定义其文本表示形式以用于调试目的的类型采用。当对象写入OutputStreamType时,将使用此文本表示形式。

protocol DebugPrintable {
    var debugDescription: String { get }
}

文档(感谢@MartinR)

注:正如评论中@Antonio和@MartinR所提到的,这在playground中不起作用(至少在Xcode6 GM中),这是已知的错误。它可以在编译的应用程序中使用。

从Xcode6 GM版本说明中:

在Playgrounds中,println()忽略了用户定义类型的Printable符合性。(16562388)

从Swift 2.0开始,Printable现在变成了CustomStringConvertible。一切都与以前相同,您仍然需要实现

 var description: String { get }

现在它被称为CustomStringConvertible。而debug是CustomDebugStringConvertible。


1
你确定这个可行吗?我也这么想,试了试 playground,显示出了类似__lldb_expr_551.Test的东西。无论是否实现了Printable - Antonio
1
还有这里有详细的文档:https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/Printing.html。 - Martin R
1
有趣。它在编译的应用程序中运行,但在游乐场中却不行。 - Martin R
这就是为什么... 我知道它是“可打印的”,但在验证后它并没有起作用,所以我认为我错了。实际上是因为是playground的问题。感谢@MartinR。 - Antonio
@Antonio 经过一番搜索,我在 Xcode 发布说明中发现 Playground 忽略了 Printable(已知问题)。感谢你指出来。我已经编辑了答案以反映这一点。 - Mike S
@MartinR 感谢您提供的文档链接,我知道它在某个地方,但我还没有找到它。我已将链接添加到答案中。 - Mike S

4
在Swift 5中,苹果引入了自定义字符串插值。
假设你有一个名为person的结构体,它具有两个属性:name和age。
struct Person {
  var name: String
  var age: Int
} 

如果您想要添加一种特殊的字符串插值方式,以便我们可以以描述性方式打印人员信息,我们可以使用一个新的appendInterpolation()方法向String.StringInterpolation添加扩展。

 extension String.StringInterpolation {
       mutating func appendInterpolation(_ person: Person) {
       appendInterpolation("My name is \(person.name) and I'm \(person.age) years old.")
    }
}

现在,如果我们要打印人员的详细信息,可以这样做:
 let person = Person(name: "Yogendra", age: 28)
 print("Person Details: \(person)")

输出结果将是:

Person Details: My name is Yogendra and I'm 28 years old.

1
我希望在这里提供一种替代方案:
Swift中的字符串插值协议是StringInterpolationConvertible。也就是说,实现该协议的任何类都可以从字符串插值构造。
回到问题上来,要控制类A实例的字符串插值打印出什么,需要创建一个字符串扩展并重载init(stringInterpolationSegment expr: A)函数。
extension String {
    init(stringInterpolationSegment expr: A) {
        //do custom work here
        //for example: self.init(expr.description)
    }
}

如果你正在寻找一种方法来消除插值可选变量时令人讨厌的“Optional(...)”,我认为这是人们想要控制对象打印方式的主要原因,只需查看 pod NoOptionalInterpolation here
额外信息(已编辑): 确认覆盖“description”仅适用于您自己的结构/类,而不适用于现有的结构/类,例如IntOptional

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接