DEV Community

Aly Yakan
Aly Yakan

Posted on

Representing Any Object in Swift Using Protocol Extensions

This article was written using Swift 4.2

I think that the single, most-used debugging tool many developers use is the print statement. For many cases, the print is enough for debugging common errors and for that, we most probably end up printing objects that we use in the code.

Sometimes, all we want is just a simple, pretty presentation of an object and all of its properties and values… and I got tired of writing a description function for every object I want to print.

Through SO, I managed to somehow scrape a piece of code that can be written once in your project and you would be able to use it on any object to print a pretty representation of all its properties and their associated values.

How did I manage to do it, you ask? With the help of a protocol, an extension, and a protocol extension. At first, I thought of extending Swift’s NSObject to write a function that would be accessible to all classes inheriting from it, but then I remembered structs. Swift’s structs are a lightweight representation of classes that cannot inherit from anything, and a lot of today’s iOS apps and libraries rely on such structs to represent their data and therefore I couldn’t just discard them.

Protocol + Extension: A true love story

We all know that a Protocol allows you to write some sort of contract specifying a bunch of properties and methods that any object conforming to this protocol should implement. We also know that an Extension allows you to extend any class or struct with more methods and computed properties even if that class is part of a third-party library that your project is using, for example, you can extend the Swift’sArray to offer convenience methods that you repeatedly use on your arrays.

But what some of you might not know is that you can write an extension on a protocol to provide a concrete implementation of some or all methods defined in a protocol. As a result, any object conforming to that protocol does not have to implement these concrete methods and will have that implementation by default! Pretty sweet. This means that I can write a protocol say, Presentable that defines a read-only property called dictionaryPresentation, and then write an extension on that protocol that implements the getter for this property and boom, any objects, class or struct, that conforms to Presentable will have this dictionaryRepresentation automatically.

This looks fine but it’s not enough to be printed in a pretty way. And as I said, we’re going to use a protocol, an extension, and a protocol extension and we’ve only the first and last ones. So let’s go ahead and create an extension on the Dictionary class to print its contents in a presentable way.

And we’re basically done! Go ahead and try this out in any project of yours. For example, if you have a Person struct, set it to conform to Presentable and then call something like print(Person().dictionary.pretty).

Discussion (0)