Cleaner Table View Data Source Code with CaseIterable

I’ve had a real drive to clean up my table view code when switching between cells and sections. I’ve been craving a data structure that keeps track of:

  • The sections in a table view.
  • The classes that are used in that section, and
  • the reuse identifier.

A couple months ago I stumbled upon a solution to this problem when I found a new protocol in Swift 4 called CaseIterable. I wrote this code to support some simple repeated logic in table view, which cleaned up a lot of code and made it a lot safer. An example:

    enum CellSection: String, CaseIterable {

        case overview = "Overview"
        case schools = "School"
        case jobs = "Job"
        case skills = "Skill"
        case projects = "Project"
        case other = "Other"
    
    }

Now by defining my sections as an string enum, I was able to clean up my data source code. For instance, my numberOfSections(in:) method became:

    override func numberOfSections(in tableView: UITableView) -> Int {
        return Section.allCases.count
    }

This became safer than simply hardcoding the return value, as it changed with the enum case changes. Additionally, I’ve occasionally made the string in this enum both the ReuseIdentifier and the classname for the cell class. For example:

    enum CellSection: String, CaseIterable {

        case overview = “Resume.OverviewCell”
    
    }

By doing this I can make my registration process more declarative.

    tableView.register(NSClassForString(CellSection.overview.rawValue), forCellReuseIdentifier: CellSection.overview.rawValue)

In my tableView(_:cellForRowAt:) method I started using:

        let section = CellSection.allCases[indexPath.section]
    let cell = tableView.dequeueReusableCell(withIdentifier: section.rawValue, for: indexPath)

Because CaseIterable returned the section in the order it was defined, my CellSection enum declared the type of cells available in the order that appeared. This made my table view data source code more declarative. Additionally, I avoided a problem I’ve seen many times before where indexPath.section is compared against a hardcoded integer in many spots in a data source. A good example implementation would be a sample tableView(_:numberOfRowsInSection:) implementation:

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        let section = CellSection.allCases[section]
        
        switch section {
        case .overview:
            return modelArray.count
        }
    }

Now, if I introduce a new section, I need to implement it in this switch. If I’m not going to use this section, I simply return 0. If Since switches in Swift must be exhaustive, I get an additional compile time check to ensure I haven’t implemented this data source improperly. If I decide I don’t need that safety I can use a default case.

By adding that, I’ve cleaned up my table view code so that the table view’s sections are much more apparent and added so safety checks to prevent me from hanging myself later on.

MUS Beta–Build 19

Resolved Issues:

  • Upon first launch app would not load user’s music without first force quitting the app. This has been resolved.
  • Startup has been optimized to be quicker.

Further Enhancements for 1.0

  • Now playing screen—redesign
  • Find screen redesign—redesign
  • User onboarding
  • Other settings.
  • Global styles

Known Issues:

  • When returning to the app from the background, the play button icon is out of sync
  • App displays incorrectly on iPad.
  • On rotation, the now playing screen does not display correctly.
  • In certain circumstances playing audio from MUS will play over the system player or other apps playing audio.

MUS Beta–Build 16

Resolved Issues:

  • Queue enhancements. App now plays all music in background with proper queueing
  • Do not autoplay when returning to the item screen
  • Now playing on home screen
  • Now playing on watch.
  • Remote events (AirPod ear remove)

Further Enhancements for 1.0

  • Now playing screen—redesign
  • Find screen redesign—redesign
  • User onboarding
  • Other settings.
  • Global styles

Known Issues:

  • When returning to the app from the background, the play button icon is out of sync
  • App displays incorrectly on iPad.
  • On rotation, the now playing screen does not display correctly.
  • On application startup, the app takes a few seconds to display it’s root view. Further optimization is needed.
  • In certain circumstances playing audio from MUS will play over the system player or other apps playing audio.

Safe Layout Guides and iPhone X.

Looking through the simulator on iOS 11 on an iPhone X the genesis for the safeAreaLayoutGuide API became so obvious to me. To account for the notch and the rounded corners of the screen, Apple added information about the sides of the screen as well as the top and bottom for us to use. (The latter being conveyed in the now deprecated topLayoutGuide and bottomLayoutGuide). I’m still not exactly sure how to “embrace the notch” in my projects though.

Regex101.com

I wish I had a tool like this while coding a several scripts a couple years ago; It’s compatible with PCRE, Python and JavaScript regex syntax. The explanation sidebar is killer.