Cleaner UITableViewControllers

Don’t make the code more difficult than it needs to be

Image for post
Image for post

When Xcode generates a default UITableViewController, and it encourages everything to go into this single view controller. This can mean a large class that is difficult to maintain, and yet this is how production code is often shipped.

It is possible to separate out the dataSource from the view controller, and should be considered as an approach if the controller starts to get too large.

Prerequisites:

Standard table view

You can simply add a TableViewController

Image for post
Image for post

and it is essential for us to add the cell identifier. I call this “cell” for this example.

Image for post
Image for post

Setting up the view controller as a UITableViewController

Image for post
Image for post

The datasource and delegate are hooked up from Interface Builder. The required methods set the number of rows for the table view and return the cell for each row. Since I named the embedded cell “cell” this has to match the one in cellForRowAt.

Image for post
Image for post
Image for post
Image for post

The data array is populated when the view loads

Image for post
Image for post

The whole view controller is here, I also implemented a headerView to maintain consistency in appearance with the other view controllers.

Embedded table view

An alternative approach is to embed the table view in a standard view controller. Note that I have to choose a new identifier for the embedded cell, and here I chose “embeddedcell”

Image for post
Image for post

Which is set up view controller conforming to UITablveViewDataSource and as a delegate of UITableViewDelegate.

Image for post
Image for post

This means that we need to set up an outlet to hook Interface Builder into the view controller.

Image for post
Image for post

and ensure that the data source and delegate are set.

Image for post
Image for post

It is debatable how much more flexibility thus gives us over the header (and possibly footer) defined in an ordinary UITableViewController.

What is certain, however, is that we have a large class with things that arguably a view controller should not “know about”

Let us split that out into the following sections:

A lighter view controller

Similar to the embedded version above, but of course we need an extra file for the data source, and we require a reference to it from our view controller:

Image for post
Image for post
Image for post
Image for post

The data source will still require cellForRowAt and numberOfRowsInSection.

We have separated the data source into the separate file.

https://github.com/stevencurtis/cleantableviews/blob/master/CleanTableViews/LighterStaticViewController.swift

https://github.com/stevencurtis/cleantableviews/blob/master/CleanTableViews/LighterStaticViewDataSource.swift

With the following data source

However, there might be an issue if you want to pass the data from the view controller to the data source. How would we do that?

A lighter view controller with data in the view controller

As an example, we can absolutely pass the data from the view controller to the data source. Within the view controller we will pass our data

Image for post
Image for post

which involves creating an initialiser for our data source:

Image for post
Image for post

The completed code is here:

The Twitter contact:

Any questions? You can get in touch with me HERE

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store