Swift: Using Complex Enums To Improve TableViews

One of the things that puzzled me about Swift when it came out was that you could put functions in an enum! That seemed like a pretty crazy pattern. I’m used to thinking of enums exactly as that – enums where I can specify values that are mapped into number. That’s it!

However, as I’ve been working on a few simple Swift TableViews and CollectionViews this week, I fell in love with how simple the complex Swift enum can make things. I’d like to share the pattern I’ve been experimenting with, and I’d love to hear what you think about it in the comments.

I’m going to build a very simple table view of Minions (from Despicable Me). Each cell in the table view will only have the image and name of the relevant minion:

minions table view

I built my enum as more of a data object:

enum MinionIndex: Int {
        case DAVE, BOB, JERRY, JORGE, KEVIN, MARK, PHIL, STUART, TIM
        
        static let minionNames = [
            DAVE : "Dave", BOB : "Bob", JERRY : "Jerry",
            JORGE : "Jorge", KEVIN : "Kevin", MARK : "Mark",
            PHIL : "Phil", STUART : "Stuart", TIM : "Tim"]
        
        func minionName() -> String {
            if let minionName = MinionIndex.minionNames[self] {
                return minionName
            } else {
                return "Minion"
            }
        }
        
        func minionImage() -> UIImage {
            return UIImage(named: "Minion\(minionName())")
        }
    }

Besides just mapping a minion to an int, there is a static dictionary that maps the minion’s index to a minion’s name, a function that gets the minion’s name from that static dictionary, and a function that returns the minion’s image.

This makes my tableView:cellForRowAtIndexPath: method very simple:

override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
        let cell = tableView.dequeueReusableCellWithIdentifier(minionCellIdentifier) as UITableViewCell
        
        if let minionIndex = MinionIndex.fromRaw(indexPath.row) {
            cell.textLabel.text = minionIndex.minionName()
            cell.imageView.image = minionIndex.minionImage()
        }
        
        return cell
    }

Notice how the data – index, name, image of the minion – stays together in the enum. In Objective-C, I would have had an enum, an array of minion names, and likely a function to convert minion names into an image, or worse – I could have used Switch statements to make a much longer tableView:cellForRowAtIndexPath: method. In fact, my coworker @louielouie actually calls this the “anti-switch-statement pattern”.

Overall, I’ve been enjoying using this pattern for my new iOS 8 Swift TableViews.

Let me know what you think!

You can view the full source code on Github here.

Enjoy the article? Join over 20,000+ Swift developers and enthusiasts who get my weekly updates.