[Swift] Don’t use a protocol when a struct would do a better job

Code in Swift
3 min readMar 30, 2022

In the previous article we created a selection list that can work with any value that conforms to Selectable protocol.

This protocol is used for two things: providing a title and an optional icon for displaying in our list and making sure that the models can be compared with the help of the Equatable protocol.

It works well and at first glance there’s nothing wrong with it. But it actually has a problem that’s been bothering me for a while.

Imagine we have a Driver model that looks like this:

We want it to conform to Selectable and it’s very easy to do. In fact we already have an icon property, so it feels like half of the work is done.

Unfortunately this won’t compile. The Selectable protocol expects an optional icon property, and Driver’s one isn’t. It seems counterintuitive that you can’t satisfy an optional requirement with a regular one, but that’s how the compiler works.

Issues with protocols

There are also other probles with this solution.

Let’s imagine that Driver’s icon property is optional and fits the protocols requirements. We still have part of our conformance (icon) in the struct and the other part (title) in the extension. It’s not a big deal, but it makes understanding the code a little bit more difficult. It would be nice if everything was in the same place.

The other problem is, the title property is kind of the same as name property, isn’t it? Once again, it makes for messy and non-obvious code. If you encountered both of them in the Xcode’s autocompletion panel, you wouldn’t know which one to use and why.

Also, imagine that we already have a title property in our Driver struct but it contains a value that is different from the one we need. What then? Again, it will lead to messy, non-obvious code.

But most importantly, the model shouldn’t know about the specific UI requirements at all. Providing a title and an icon isn’t its responsibility. So our implementation of Selectable protocol is wrong to begin with. In fact, we don’t need it at all.

Protocol witnesses

Protocol Witness is a fancy name for a struct with generic parameters. There are some great articles about them, the latest I’ve read is this one. They are mainly used to convert problematic protocols into perfectly working generic structs.

So let’s start by deleting the Selectable protocol and removing unnecessary code from our Driver struct. The only thing it needs to do is conform to the Equatable protocol.

So far, so good. But we need a way to extract a title and an icon from the Driver struct (or any other Equatable model) to display them in our list. That seems like a job a function would do well. So let’s define such a function and give it a typealias for ease of use.

Now we add it to our SelectionList model that is used to simplify initialization of the SelectionListViewController.

And here’s how you would use it.

If you liked this article please retweet it on Twitter or share it in any other social network. It helps more than you think!

--

--