Struct-Style Printing of Classes in Swift

In Swift, printing a struct outputs its name and properties. But printing a class only outputs its name. Here’s why, and how to fix it.

When printing, if Swift can’t determine a string representation for a value, it instantiates a Mirror and creates a string out of that. This “ad-hoc” printing is performed differently depending on whether the value is a class or a struct.

Consider this struct example:

Which outputs:

Person(name: “Matt”, age: 32, social: Social(twitter: “@mattcomi”))

Great, right? But if I were to make Person a class, (provide an initializer) and leave everything else alone, it would output this:


Not so great.

This happens because a Mirror has a (read-only) DisplayStyle property that determines how the Mirror should be interpreted for display, e.g. when printing. When the DisplayStyle is struct, you get detailed output. But when it’s class, you get the class name and that’s it. If you want to see for yourself, download the Swift source code and refer to the _adHocPrint_unlocked function in OutputStream.swift.

The upshot is, if you want struct-style output, you have to conform to CustomStringConvertible and implement description yourself:

But that’s annoying and error-prone and it sucks. There must be an easier way, right? No. Wait, I mean yes:

  1. Implement a protocol that conforms to CustomStringConvertible and call it, let’s say, ReflectedStringConvertible.
  2. Create a ReflectedStringConvertible extension that implements description using a Mirror and provides struct-style output for classes.

Here’s one I prepared earlier:

This protocol allows any class to be printed as if it were a struct. To use it, your class must simply conform to ReflectedStringConvertible. You don’t even need to implement anything, the extension takes care of that. Here it is in practice:

Which outputs:

Person(name: “Matt”, age: 32, social: Social(twitter: “@mattcomi”))

Done and done. If you’re interested in using ReflectedStringConvertible, you can grab it from GitHub.