TableViews, collectionViews and Swift enums

:  ~ 1 min read

I talked about how we can have a safer and cleaner tableView/collectionView section handling, but we can improve it even further, with protocol extensions:

protocol Countable {

  var rawValue: Int { get } // 1
  init?(rawValue: Int) // 2

  static var count: Int { get } // 3

}

This is a protocol that mimics an enum that conforms to Int: it has a rawValue of type Int (1), it has an initializer based on said rawValue (2), and it has a static var (3) that will be used to hold the total number of cases. And here's where extensions come into play:

extension Countable {

  static var count: Int {
    var max = 0 // 1
    while let _ = self.init(rawValue: max) { max += 1 } // 2
    return max // 3
  }

}

We start from 0 (1), and, as long we can create a case from the current max, we keep incrementing max by 1 (2). When a case can no longer be created, it means we previously reached the last valid case, so we will return max (3) -- one valid case means 0 + 1 = 1, two mean 0 + 1 + 1 = 2, and so on.

Then, when we create an Int enum, we just have to also conform to Countable, and we'll have the number of cases out of the box:

private enum Section: Int, Countable {
  case products
  case shippingDetails
  case paymentDetails
  case totalValue
  // numberOfSections - we don't need this anymore
}

print(Section.count) // 4

As I mentioned in the previous post, this approach only works for UITableViews and UICollectionViews, but does so perfectly.