Swift – the Swift equivalent of -[NSObject description]

swift

In Objective-C, one can add a description method to their class to aid in debugging:

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

Then in the debugger, you can do:

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

What is the equivalent in Swift? Swift's REPL output can be helpful:

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

But I'd like to override this behavior for printing to the console:

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

Is there a way to clean up this println output? I've seen the Printable protocol:

/// 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 }
}

I figured this would automatically be "seen" by println but it does not appear to be the case:

  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)

And instead I have to explicitly call description:

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

Is there a better way?

Best Answer

To implement this on a Swift type you must implement the CustomStringConvertible protocol and then also implement a string property called description.

For example:

class MyClass: CustomStringConvertible {
    let foo = 42

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

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

Note: type(of: self) gets the type of the current instances instead of explicitly writing ‘MyClass’.