Using Swift Enums as Stateful Data Models

Petros Demetrakopoulos
Jan 15 · 4 min read
Image for post
Image for post

Swift brought more power to a feature already known from the Objective-C days, enumerations.

However, unlike Objective-C enums which could enumerate related names only to Integer values, Swift enums are much more flexible and do not obligate the developer to provide a value (also known as a “raw value”) for each and every case as Objective-C enums did.

Swift enums also come with associated values, computed properties, instance and methods, initializers, conform to protocols and many more features that empower them to use them as models for our data. Yes, we can use enums almost as we can use classes and structs! And many times it is easier to maintain state and test our code by preferring enums over classes or structs (mainly for smaller amounts of data).

But there is no better way to demonstrate all the features and use cases of Swift enums, than using an example:

Let’s say that we want to model a pizza.

If we try a struct to do this, it would look like this:

The problem that emerges from this setup is that if the model contains properties related to state (as isBaked and isDelivered in the example above), it seems that an instance could possibly be (erroneously) in 2 different states at once while it should not. As you can easily understand, nothing protects us from setting isDelivered to true and isBaked to false to true, while this should not be allowed (as we have made the assumption that a Pizza can be delivered only if it has been baked previously).

Most models also come with or participate in actions that trigger state changes. Swift enums allow us to group associated values related to an action that triggers a change in the state of our model. Thus, we can protect ourselves from setting state properties to values that should not be set. The actions handle state changes now autonomously. In Swift enums, different states are grouped in cases that have associated values which are used as the state properties.

Actions are just mutating functions, which means that they can change (mutate) the variables of our enum and therefore, the current sate.

So we could transform the Pizza struct to enum in order to take advantage of the unique possibilities that Swift enums offer.

Now, each case in the enum represents a different and discrete state in which a Pizza instance can be.

In this implementation, the properties isBaked and isDelivered will be derived from the current state. We also declare a currentState variable that returns a literal mentioning the current state of a Pizza instance. We could say that the following two computed properties act the same way as the getters in an analogy with a normal Class.

But how do we change the state of an instance?

As we previously mentioned, actions trigger state changes. In enums, actions are modeled through mutating functions. Before we code the mutating functions we should think which state changes can be done and which state changes are not allowed. So, in this scenario let’s say that after we prepare a pizza, we can then add extra ingredients or bake it. Adding extra ingredients is optional. Also, we cannot deliver a pizza if it is not baked and we cannot add extra ingredients in a pizza that is already baked or that it has been already delivered. We would then prefer not to be able to deliver or bake a pizza twice.

These rules consist the transition function of our model.

We now have to convert these rules in cases according to input states. The mutating functions are shown below. As you can see, when we want to move from one state to another, we simply assign the new state to self. If the transition is not allowed for any reason, we print a relative message.

State transition functions

Then we can use the model we just created as shown below.

Important note: Instances should always be variables (declared with var) in order to be able to change states.

If we run the code below we should get the following output.

Image for post
Image for post
Output

You can find the complete project in Swift playground format in this GitHub repository.

Thanks for your time! I hope you enjoyed.

Code Story

Sharing everything we know about design and development.

Thanks to The Startup

Petros Demetrakopoulos

Written by

💻Code-blooded, 🌏 Traveler ⌨️ Computer Science graduate, AUEB alumnus. Passionate Homebrewer🍺. Lifelong learner 📚.

Code Story

Sharing everything we know about design and development. A new publication by The Startup (https://medium.com/swlh).

Petros Demetrakopoulos

Written by

💻Code-blooded, 🌏 Traveler ⌨️ Computer Science graduate, AUEB alumnus. Passionate Homebrewer🍺. Lifelong learner 📚.

Code Story

Sharing everything we know about design and development. A new publication by The Startup (https://medium.com/swlh).

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store