什么是Swift相当于 – ?
在Objective-C中,可以在其类中添加一个description
方法来帮助debugging:
@implementation MyClass - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p, foo = %@>", [self class], foo _foo]; } @end
然后在debugging器中,你可以这样做:
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)
相反,我必须明确地调用description:
8> println("x = \(x.description)") x = MyClass, foo = 42
有没有更好的办法?
通过一些实验,我发现Printable
和DebugPrintable
协议在编译实际应用程序时工作,但不在REPL或Playground中。
注意 :你写的代码是正确的,但在这种情况下,你可能正在寻找DebugPrintable
Swift已经将这些协议重命名为CustomStringConvertible
和CustomDebugStringConvertible
– 虽然编译器当前有帮助地告诉你它已经完成了:)
在Swift中使用CustomStringConvertible
和CustomDebugStringConvertible
协议的例子:
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或者基础库中包含的任何类inheritance,那么使它inheritanceNSObject
类或者使它符合CustomStringConvertible
和CustomDebugStringConvertible
协议。
只需使用CustomStringConvertible
和var description: String { return "Some string" }
适用于Xcode 7.0testing版
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))" }
有关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!"
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