How not to use enums in Swift

In Swift, enums are powerful. So powerful in fact, that it’s easy to abuse them.

Here are some examples of enum abuse, and alternative approaches.

App themes

When adding dark theme to your app, instead of a boolean flag, you may add enum like this:

enum Theme {
    case dark
    case light
}

Sure, using an enum here seems like an obvious choice. But features expand, and you may want to add multiple themes. Or even custom themes. This enum can become something like this:

enum Theme {
    case dark
    case darkAlternative
    case light
    case red
    case darkRed
    case custom(foreground: UIColor, background: UIColor)
}

You may make it easier to live with by adding computed properties for colors, but you’d be fighting the system. A struct is more appropriate.

struct Theme {
    var background: UIColor
    var foreground: UIColor

    static let dark = Theme(background: .black, foreground: .white)
    static let light = Theme(background: .white, foreground: .black)
}

This way, it is easier to add any new themes, and they can even be defined from outside the app (like configuration file or backend).

It is also leads to cleaner code. With an enum, you need huge switch blocks, and with this approach, all values can be defined in a single place.

Table view data

I have seen code like this:

class ViewController: UITableViewController {
    enum Sections {
        case header(Header)
        case items([Item])
        case otherItems([OtherItem])
    }
}

This is no better than huge if…else block in cellForRowAt when you have to replace it with a big switch…case. It may be true that sections are enumerable, but representing sections in table view is more natural using a 2D array. Or multiple arrays. Or even a custom type representing it.

The way I would do it is having a protocol named TableCellModel (or something like that), where you would define what data cell holds, and what cell it shows. There are numerous libraries which make this easier such as Owl or RxDataSources.

This is an opinion

Of course, these examples are not always applicable, and depend on context. If, for example, you are sure you will only have dark and light theme, sure, use an enum. It’s better then a flag (don’t use a flag… Never use a flag).

In my experience, pushing advanced features of Swift (or any other language) too aggressively, can cause trouble down the line. Sure, they are useful in some cases, but not everything is a nail.