The combination of an
NSFetchedResultsController and a
UITableView provides a powerful way to integrate Core Data with a user interface. The greatest benefits of using
NSFetchedResultsController come when we use it to automatically update a table view when objects are added, updated, or removed from a Core Data data store. First things first, though…
With a Core Data data store seeded with data, the next logical step is to display that data somewhere other than the console. This post will be devoted to figuring out how to set up an
NSFetchedResultsController to display data inside a
A follow-up post has been published to help you keep the table view in sync with the data as it changes in your persistent store, so once you’re finished here, you might check out that next step!
NSFetchedResultsController will help us accomplish two things:
1) It will fetch data from the Core Data data store
2) It will use some of the data we fetch to populate various pieces of the UI (table view section headers, cell “title” and “subtitle” text. Here’s what we’re going for:
Setup and resources
I’m continuing my “Zootastic” example that I used to write about using Swift to seed a Core Data database. In fact, I’ve simply branched the project on GibHub and added the things we’re exploring in this post.
For this entry, we’ll still be dealing with our three primary
NSManagedObject subclasses: Zoo, Animal, And Classification:
Zootastic is a single view application. The Storyboard contains one view controller with a table view filling the Scene.
The table view is using one prototype cell with an Identifier of “Cell” (for simplicity). The Style of the prototype cell is set to Subtitle.
MainViewController.swift is where the action is happening. Here’s a quick outline of what we need to accomplish in this class:
MainViewControlleris a class concerned with being the table view’s data source and delegate. Additionally, it will serve as the
NSFetchedResultsControllerDelegate. For this post, we won’t actually need the fetched results controller delegate functionality to display data. Those methods are particularly useful for synchronizing things when data changes.
With the class declaration out of the way, we’ll investigate the class implementation one section at a time.
Maintain NSManagedObjectContext instance reference
application:didFinishLaunchingWithOptionsmethod. More on this, shortly…
For now, know that we’re counting on that later step to take place, since
context is defined as an implicitly unwrapped optional.
Create and configure NSFetchedResultsController instance
Next, we need to create and configure an
NSFetchedResultsController instance. Here’s a bit of code with comments to follow:
Within the closure expression, I’m setting up a fetch request with some sorting applied. All that’s left is to initialize the
NSFetchedResultsController, set its delegate and return it.
Once the view has loaded, the idea is to perform the
NSFetchedResultsController instance’s fetch request so that it has data to use in our
UITableViewDataSource methods. This is how to do it:
The final step in implementing
MainViewController is to set up the table view so that it pulls data from
fetchedResultsController. I’m implementing the standard UITableViewDataSource methods here, along with
tableView:titleForHeaderInSection. Take a look:
Apart from a bit of
if let ___ = ___ syntax, there’s not an awful lot of surprising code here if you’re familiar with working with table views. I’ve highlighted the relevant code related to
fetchedResultsController. Without using
NSFetchedResultsController, you’d probably supply data to the table view from an array or a dictionary or both. The
fetchedResultsController code simplifies the data display dilemma when you’re using Core Data.
UITableViewDataSource methods are implemented, the implementation of
MainViewController is complete for this example.
There’s one final thing we need to do in order to get things rolling. In the “maintain NSManagedObjectContext instance reference” section of this post, I mentioned the strategy for assigning the
NSManagedObjectContext instance in the
MainViewController. Here’s how I do it:
Note: With iOS 13, the code to assign the
managedObjectContext to the root view controller needs to go in your app’s SceneDelegate.
The portion new to “injecting” the
MainViewController is highlighted. I simply grab a reference to the
rootViewController (which in our example is the
MainViewController) and cast it to the appropriate type. Then I set the
context property to the
managedObjectContext that’s created in the
AppDelegate via Xcode’s auto-generated Core Data stack setup.
If you’re using Core Data in your iOS application, the combination of an
NSFetchedResultsController and a
UITableView provides a powerful way to integrate data from your data store into your UI. We’ve explored how to display data in a table view using
NSFetchedResultsController. Feel free to grab the GibHub project for further investigation and to see Zootastic in action.