Swift enums for managing UITableView sections

Mario Boikov
3 min readApr 11, 2016

--

In this article I’ll show you how you can utilize Swift enums to make UITableView section management more safe. The solution is probably only suitable for table views which have a predefined set of sections and not for table views with dynamically number of sections.

Typical solution

A typical solution is to declare integer constants for each section in the table view. The example below shows how a Section struct could be defined with constants where each constant represents a section index in a table view:

struct Section {
static let Name = 0
static let Address = 1
static let Phone = 2
static var numberOfSections { return 3 }
}

At least two potential problems arise when plain integer constants are used for table view sections.

  • You need to manually assign section numbers. What happens if you remove a constant? The compiler can’t tell you if there’s a gap in the sequence between the first and the last constant.
  • How can you assure that all sections are handled in the UITableViewDataSource/UITableViewDelegate adoptions? Unfortunately, the compiler can’t assist you with that when plain integer constants are used.

So let’s take a look at how enums in Swift can be used to solve the two issues above.

The enum solution

I assume you already know the basics about defining enums, declaring cases and raw values. If not, please take look at the Enumerations section in the Swift documentation.

When defining an enum the cases can be pre-populated with values of the same type, e.g Int. The snippet below shows how the previous example can be re-written using enum instead of struct.

enum Section: Int {
case Name
case Address
case Phone
init?(indexPath: NSIndexPath) {
self.init(rawValue: indexPath.section)
}

static var numberOfSections: Int { return 3 }
}

If a case (of type Int) isn’t explicitly given a value, Swift will automatically generate one. A case will be assigned a value of one more than the previous case and if the first case isn’t explicitly given a value, it will be set to zero.

By declaring a constant as a case in an enum, we no longer have to manually assign section numbers and thus have eliminated the first problem. The compiler will do the assignment for us without the risk of introducing gaps between the first and the last constant. We can reorder the cases without having to worry about getting the section numbers wrong.

By declaring constants in an enum, the potential of introducing gaps in the number sequence between the first and the last constant is eliminated.

The second problem is actually very easy to solve, if you stick to two simple rules:

  1. Use switch when handling cases.
  2. Make sure not to use the default case to make the switch statement exhaustive.

If you follow the two rules above the compiler will give you an error if you miss handling one of the cases in a switch. The compiler will also give you an error when you add or remove a section.

Use switch and make sure not to use the default case. The compiler will help you finding non exhaustive switch statements.

If you only need to check for one of the cases I’d recommend using an if statement instead. I think the intention will be more clear with an if in those situations because you’re only interested in handling one particular case.

The example below gives you an idea how the implementation of numberOfRowsInSection function could look like.

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
switch Section(rawValue: section) {
case .Name?: return 1
case .Address?: return contact.address.count
case .Phone?: return contact.phone.count
case .None: return 0
}
}

Please visit the sample project at Bitbucket which demonstrates how the technique discussed in this article can be used.

Anyone know if there’s a way to find out how many cases there’re in an enum?

--

--

Mario Boikov

Owner Red Shark AB. Software developer with passion for UI/UX. Wannabe guitarist.