Creating Enums with Custom Raw Type in Swift

February 11th, 2022

⏱ Reading Time: 5 mins

As developers who write code for the Apple ecosystem in Swift, we use enums all the time in order to represent lists of values that are meaningful to our programs. Enums can contain simple cases, but quite often there are raw values matching to each case. As an example, see the following that represents week days; each day has been assigned with an integer number starting from 1:

Enums with raw values just like the above are pretty handy in programming. We can easily get the raw value of a case using the rawValue property, as well as to get a case based on a raw value. And that is because an enum with raw values automatically conforms to RawRepresentable protocol once we declare the value type.

Usually, raw values are of basic Swift data types, such as Int, String, Double, etc. However, it’s absolutely possible to create enums with raw values of custom types as well. There are a couple of rules to follow in order to manage that, but nothing complicated or confusing. That said, let’s find out what it takes to create an enum with a custom raw type.

Preparing a custom type

Let’s suppose that we want to represent the status of a task visually, and that there is a different color to show for each status case. An enum is obviously the perfect choice to keep all various cases programmatically. But for the purposes of this demonstration, we’ll also create a custom type for representing a status color.

Being specific, this new type will be containing a string property which will be representing a color as a hexadecimal value. In addition, a computed property will be returning the actual color object, so we can use it later in a view.

Here’s the implementation of all that:

Note: Instead of NSColor, A UIColor, or a SwiftUI Color could be returned as well from the color property above. I just chose to demonstrate today’s topic in a macOS project.

I mentioned earlier that there are certain rules to follow when it’s necessary to create enums with custom raw types. In fact, there are two of them, and they regard the custom type only.

The first rule is that our custom type should be conforming to the Equatable protocol:

Note that you might need to implement the ==(lhs:rhs:) protocol’s method manually if the data types of the stored properties do not conform to Equatable already. This is not the case here, as hex is a String value, and String conforms to Equatable.

The second rule to respect is that the custom type should also be conforming to any of the following protocols, so it can be expressed as a string, integer, or float literal respectively:

  • ExpressibleByStringLiteral
  • ExpressibleByIntegerLiteral
  • ExpressibleByFloatLiteral

In the specific example of this post the StatusColor type must conform to ExpressibleByStringLiteral protocol:

By doing that, it becomes mandatory to implement the following initializer in our type as well:

The StatusColor type is now ready to be used as the raw type in enums.

An enum with the StatusColor raw type

The following enum represents the various statuses of a task:

Right now there is no raw type declared, but we’ll change that by setting the StatusColor implemented right above. In addition to that, we’ll also specify the desired color for each case. But we won’t assign StatusColor instances as values; since our type conforms to ExpressibleByStringLiteral protocol, we’ll just assign hex string values as shown next, and the compiler will take care of the rest:

Putting in motion the enum with the custom raw type

In a SwiftUI view now, we’re going to give a try to the above enum in order to visually show the various statuses along with the matching color. The first thing we’ll do is to define an assistive method marked with the @ViewBuilder attribute. The method will return a SwiftUI view, an HStack in particular, which will be containing a title for the status and a color. Here’s its implementation:

See that both the status title, as well as the indication are given as arguments. But more important than that is to notice how we access the actual color through the given StatusIndication case; we first access its raw value, which is a ColorStatus object, and then through that the color computed property:

In the view’s body we will call the status(withTitle:statusIndication:) method as many times as the various statuses, passing each time a different case:

By running this simple app we get this:

A macOS window showing the four statuses one after the other with the respective titles and matching colors.

Of course, and as it also happens with enums with built-in raw types, we are able to get the case of an enum by providing the raw value. For instance, take a look at the following; at first we create a new StatusColor object, and then we pass it as the raw value to a new StatusIndication value:

Watch out however not to provide a raw value that does not match to an actual case; if that happens, the StatusIndication initialization will return a nil value.

Overview

Enums with custom raw types can become a quite powerful tool that can lead in turn to smarter and less code. When creating your own enums with custom types, make sure to comply to the two simple requirements presented previously, and the rest is easy. The simple scenario demonstrated in this post shows all you need to know in order to start using that technique in your own projects, so just go ahead and give it a try.

Thank you for reading, enjoy coding! ????????‍????

Stay Up To Date

Subscribe to my newsletter and get notifiied instantly when I post something new on SerialCoder.dev.

    We respect your privacy. Unsubscribe at any time.