什么是 Swift 等价的-[ NSObject 描述] ?

在 Objective-C 中,可以在类中添加一个 description方法来帮助调试:

@implementation MyClass
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p, foo = %@>", [self class], foo _foo];
}
@end

然后在调试器中,您可以执行以下操作:

po fooClass
<MyClass: 0x12938004, foo = "bar">

什么是 Swift 的等价物? Swift 的 REPL 输出可能有所帮助:

  1> class MyClass { let foo = 42 }
2>
3> let x = MyClass()
x: MyClass = {
foo = 42
}

但是我想覆盖打印到控制台的这个行为:

  4> println("x = \(x)")
x = C11lldb_expr_07MyClass (has 1 child)

有没有办法清理这个 println输出? 我看过 Printable协议:

/// This protocol should be adopted by types that wish to customize their
/// textual representation.  This textual representation is used when objects
/// are written to an `OutputStream`.
protocol Printable {
var description: String { get }
}

我认为 println会自动“看到”这一点,但事实似乎并非如此:

  1> class MyClass: Printable {
2.     let foo = 42
3.     var description: String { get { return "MyClass, foo = \(foo)" } }
4. }
5>
6> let x = MyClass()
x: MyClass = {
foo = 42
}
7> println("x = \(x)")
x = C11lldb_expr_07MyClass (has 1 child)

相反,我必须明确地称之为描述:

 8> println("x = \(x.description)")
x = MyClass, foo = 42

还有更好的办法吗?

45135 次浏览

要在 Swift 类型上实现这一点,必须实现 CustomStringConvertible协议,然后还要实现名为 description的字符串属性。

例如:

class MyClass: CustomStringConvertible {
let foo = 42


var description: String {
return "<\(type(of: self)): foo = \(foo)>"
}
}


print(MyClass()) // prints: <MyClass: foo = 42>

注意: type(of: self)获取当前实例的类型,而不是显式写入“ MyClass”。

在 Swift 中使用 CustomStringConvertibleCustomDebugStringConvertible协议的例子:

PageContentViewController.swift

import UIKit


class PageContentViewController: UIViewController {


var pageIndex : Int = 0


override var description : String {
return "**** PageContentViewController\npageIndex equals \(pageIndex) ****\n"
}


override var debugDescription : String {
return "---- PageContentViewController\npageIndex equals \(pageIndex) ----\n"
}


...
}

ViewController Swift

import UIKit


class ViewController: UIViewController
{


/*
Called after the controller's view is loaded into memory.
*/
override func viewDidLoad() {
super.viewDidLoad()


let myPageContentViewController = self.storyboard!.instantiateViewControllerWithIdentifier("A") as! PageContentViewController
print(myPageContentViewController)
print(myPageContentViewController.description)
print(myPageContentViewController.debugDescription)
}


...
}

打印出来:

**** PageContentViewController
pageIndex equals 0 ****


**** PageContentViewController
pageIndex equals 0 ****


---- PageContentViewController
pageIndex equals 0 ----

注意: 如果您有一个自定义类,它不从 UIKit基金会库中包含的任何类继承,那么让它继承 NSObject类或使它符合 CustomStringConvertibleCustomDebugStringConvertible协议。

只要使用 CustomStringConvertiblevar description: String { return "Some string" }

在 Xcode 7.0测试版中工作

class MyClass: CustomStringConvertible {
var string: String?




var description: String {
//return "MyClass \(string)"
return "\(self.dynamicType)"
}
}


var myClass = MyClass()  // this line outputs MyClass nil


// and of course
print("\(myClass)")


// Use this newer versions of Xcode
var description: String {
//return "MyClass \(string)"
return "\(type(of: self))"
}
class SomeBaseClass: CustomStringConvertible {


//private var string: String = "SomeBaseClass"


var description: String {
return "\(self.dynamicType)"
}


// Use this in newer versions of Xcode
var description: String {
return "\(type(of: self))"
}


}


class SomeSubClass: SomeBaseClass {
// If needed one can override description here


}




var mySomeBaseClass = SomeBaseClass()
// Outputs SomeBaseClass
var mySomeSubClass = SomeSubClass()
// Outputs SomeSubClass
var myOtherBaseClass = SomeSubClass()
// Outputs SomeSubClass
struct WorldPeace: CustomStringConvertible {
let yearStart: Int
let yearStop: Int


var description: String {
return "\(yearStart)-\(yearStop)"
}
}


let wp = WorldPeace(yearStart: 2020, yearStop: 2040)
print("world peace: \(wp)")


// outputs:
// world peace: 2020-2040

CustomStringConvertible相关的答案就是我们要走的路。就个人而言,为了保持类(或结构)定义尽可能干净,我还将描述代码分离到一个单独的扩展中:

class foo {
// Just the basic foo class stuff.
var bar = "Humbug!"
}


extension foo: CustomStringConvertible {
var description: String {
return bar
}
}


let xmas = foo()
print(xmas)  // Prints "Humbug!"

给你所述,您还可以使用 Swift 的反射功能,使您的类通过使用这个扩展生成它们自己的描述:

extension CustomStringConvertible {
var description : String {
var description: String = "\(type(of: self)){ "
let selfMirror = Mirror(reflecting: self)
for child in selfMirror.children {
if let propertyName = child.label {
description += "\(propertyName): \(child.value), "
}
}
description = String(description.dropLast(2))
description += " }"
return description
}
}