Extending enums in Swift
I ve been developing with Swift since a couple of years ago and I have even written an app with it (Knowtrail) but recently I started earning my living by coding in Swift. One thing I hadn’t really tried until now however was to extend enums.
That was because I hadn’t realized how much more powerful enums are in Swift! The problem I had to solve was that I wanted to write a manager object that could write properties on a bluetooth peripheral. These properties have a limited amount of possible values, hence the use of enums. However, each property had a different set of values and consequentely required a different enum type. But I still wanted my manager to handle all properties the same regardless of their type and these properties thus saving me lines of code and gaining me code quality and cleanliness. Mainly I wanted a centralized way to check properties have a valid value (for the perspective of my bluetooth peripheral) and also export the value from the enums into a format appropriate for writing via bluetooth (in iOS’s case this is the Data class).
Knowing that one of the huge advancements we ve had with Swift is its attitude that everything should be extendable and protocol-able I half in disbelief tried to write some methods inside my enums in order to extend them and to my enjoyment it worked!
I embed an example of what I did roughly:
Since I wanted all my enums to be able to be handled independently of their type, the Swift way to do this is through protocols. So, we can see above two protocols defined (Invalidable & Exportable) that allow any object conforming to them to supply a way for anyone to know whether the object’s value is valid and also a way to get its value in our desired format.
The Environments enum conforms to both protocols and we see in isValid() method that an enum is an object by all measures; we can access self and its properties! It also supports class inheritance, in our case UInt8. By inheriting UInt8 we get a nice side-effect: all its possible values get a UInt8 value depending on their order (e.g. .indoors is 0, .semiOutdoors is 1 etc)
Another advantage of using protocols is that it can be adopted by non enum objects and we can still export their value and check if they are valid. In my case, I had some properties with a type of practically unlimited number of options (e.g. a 32-bit integer), so I created a wrapper custom object around UInt32 and conformed it to both protocols. This way, I could have other my manager handle all my properties the same regardless of their enum type and regardless of if they were enums at all!