Core Data and Table View Controllers in Swift

If you spend some time writing iOS applications you are quite likely to come across Core Data.  And you’re even more likely to be working with UITableView objects.  Apple does not directly provide guidance on how to integrate Core Data into a UITableView through a UITableViewController.  Fortunately there are other sources of information for iOS developers.

While researching how best to integrate Core Data and Table View Controllers in Swift, I came across a class called CoreDataTableViewController (I also did a quick port to Swift).  The class provides some magic that becomes the glue between your Core Data and your view controller.  All you need to do is cough up a fetched results controller and the base class makes you into a brilliant, rock star programmer.

This little gem does a lot for you and in a pretty simple way.  CoreDataTableViewController (CDTVC) derives from UITableViewController.  So, you can use the class as the direct ancestor of your own table view controllers.  Then you just override one of the view life cycle methods (i.e., viewDidLoad()) and create an instance of NSFetchedResultsController that you hand off to the ancestor class via a property.  The base class is an instance of  UITableViewController and provides the necessary methods to satisfy a table view.  Additionally, the class conforms to the NSFetchedResultsControllerDelegate protocol so that it is aware of changes in the underlying data.

Your Direct Ancestor – Getting help from your parents

By inheriting from CDTVC you are inheriting from a full-blown UITableViewController.  Being a table view controller means that someone must implement some methods, such as func numberOfSectionsInTableView(tableView: UITableView) -> Int, func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int and func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell. CDTVC can help you out quite nicely.  It uses the fetched results controller to figure out such things as how many sections you have and how many rows are in any given section.

While CDTVC is really good, it does have its limitations.  It cannot generically implement cellForRowAtIndexPath so you’ll have to implement that method in your derived class.

Providing fetched results controller – Show me the data

Some of what makes your own implementation of a table view controller unique is the data it presents.  Each class you derive from CDTVC will need to provide the base class a fetched results controller.  Generally I implement this in the derive class’s implementation of viewDidLoad().

CDTVC understands fetched results controllers.  It knows how to get along nicely.  CDTVC conforms to the UITableViewDataSource protocol.  In doing so, it implements the methods by inquiring of the fetched results controller to determine how many sections there are and how many rows in each section.  You can quit worrying about those methods…it has you covered.

CDTVC even pays attention to the sections created as a result of the sectionNamesKeyPath argument you use when creating your NSFetchedResultsController().  If you provide a key path then the CDTVC will respect that when responding to UITableViewDataSource inquiries.  The net effect is that you get a table view with sections without having to do more than including the key path argument.  A small change to include the key path and you’re all set!

NSFetchedResultsControllerDelegate – Spying on your own data

CDTVC goes a step further for you too.  It becomes, effectively, an observer of your NSFetchedResultsController.  The benefit of this is that the class is listening for changes to the data underlying your fetched results.  When the controller observes changes it automatically updates the user interface for you.  Implementing this yourself (for every table view controller) is a lot of extra grunt work and you won’t gain anything by rewriting this every time.  Including this in the base class is a step away from the masochistic to a more sane world.

Ah, you might be thinking to yourself:  that doesn’t make sense…when would the underlying data change without me, the almighty programmer, knowing about it?  Enter iCloud.  When you are working on an application that you’d like to synchronize data across devices with iCloud then updates often happen in the backgrounds.  For example, when testing you might have your app running on an iPad and the iPad is just sitting there showing a table view of data.  You can make changes on your iPhone and the changes will “just appear” on the iPad as iCloud synchronizes the data for you.  CDTVC takes care of making sure that your UI shows the changes as they happen.

The method implementations of this protocol are not very complicated, but they are tedious if you rewrite them every time.  The code is not particularly worth reviewing, but it is important to highlight that the “just work” and that helps you look like the thoughtful, detail-oriented programmer you ought to be.

Conclusion

The CoreDataTableViewController provides you with some terrific functionality with virtually no cost.  You take the class, include it in your project, and inherit wherever appropriate.  You cut your coding down to providing an NSFetchedResultsController instance and an implementation of cellForRowAtIndexPath.  After that, CDTVC takes care of the rest, including creating table sections and automatic UI updates when underlying data changes.

This entry was posted in Core Data, Swift, Technical. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*