It is no secret that I love the Core Data framework. It does what I want it to do, mostly, and it continues to evolve over time. This year, Apple introduced several amazing additions and improvements that everyone working with Core Data is going to appreciate.
But this article is not about these changes. In this article, I would like to explore with you the new Core Data template that ships with Xcode 8. It introduces a new class of the Core Data framework and it also reduces the boilerplate code for setting up Core Data to a handful of lines. Let me show you.
Project Setup
Make sure you have a copy of Xcode 8 installed on your machine. Select New > Project... from Xcode's File menu and choose the Single View Application template from the iOS > Application section.
Give the project a name, set Language to Swift, and don't forget to check Use Core Data at the bottom of the form. That is what we are here for.
Tell Xcode where you would like to store the project files and click Create.
Exploring the Core Data Stack
At first glance, very little seems to have changed compared to previous versions of the Xcode template. Xcode has created a data model file for us, Core_Data.xcdatamodeld, and provided us with a Core Data stack in the application delegate.
Let us explore what the Core Data stack setup looks like. Open AppDelegate.swift and take a moment to explore the contents of the AppDelegate
class.
At the top, we see an import statement for the UIKit and the Core Data frameworks. That is all the new Core Data template has in common with previous incarnations. The Core Data setup itself is short and simple thanks to a new member of the Core Data framework, the NSPersistentContainer
class.
Most of what you see in the AppDelegate
class are comments. Setting up the Core Data stack is reduced to less than a dozen lines of code, which is a fraction of what it used to take to set up a Core Data stack.
We have a helper method to save the managed object context, saveContext()
, and a lazy variable property, persistentContainer
of type NSPersistentContainer
. This is what the lazy property looks like. I have omitted the comments for clarity.
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "Core_Data")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
The NSPersistentContainer
instance is initialized by invoking a convenience initializer, init(name:)
, passing in the name of the data model, Core_Data. Notice that there is no explicit instantiation of an NSManagedObjectModel
, a NSPersistentStoreCoordinator
, or a NSManagedObjectContext
. This is abstracted away by the NSPersistentContainer
class.
After initializing the persistent container, the persistent store is loaded. This step is similar to invoking the addPersistentStoreWithType(_:configuration:URL:options:)
method on the persistent store coordinator. This method accepts one parameter, a closure, which is invoked when loading of the persistent store is completed, successfully or unsuccessfully. The closure accepts two parameters, an instance of the NSPersistentStoreDescription
class and an optional Error
object.
The NSPersistentStoreDescription
class is another new addition to the Core Data framework. It encapsulates the information and configuration to add a persistent store to the persistent store coordinator. As the name of the class implies, it describes a persistent store. From a functional perspective, it is very similar to the NSEntityDescription
class you may already be familiar with.
What Is a Persistent Container?
The NSPersistentContainer
class encapsulates the Core Data stack and it is available from iOS 10, tvOS 10, macOS 10.12, and watchOS 3. It makes setting up a Core Data stack easier than ever, providing developers with a simple setup with quite a bit of flexibility.
After creating an instance of the NSPersistentContainer
class, you can easily access the managed object model and the persistent store coordinator through the managedObjectModel
and persistentStoreCoordinator
properties.
persistentContainer.managedObjectModel
persistentContainer.persistentStoreCoordinator
The class also provides easy access to a viewContext
property, an instance of the NSManagedObjectContext
class that operates on the main queue. As the name of the property implies, this managed object context is designed to be used in combination with the application's user interface.
persistentContainer.viewContext
There are several other neat features that I discuss later this week, such as the ability to create background managed object contexts and specifying the directory in which the persistent store lives by subclassing the NSPersistentContainer
class.
Should You Use a Persistent Container?
Should you use the NSPersistentContainer
class? If the deployment target of your project is iOS 10, tvOS 10, macOS 10.12, or watchOS 3, then that is certainly miles better than using the outdated Core Data stack Xcode used to ship with. Setting up the Core Data stack is much simpler and, more importantly, it is no longer tied to the application delegate.
The persistent container is what many developers have been using for years and years. You can name it a persistent container or a Core Data manager. The idea is that a dedicated class is in charge of setting up and managing the Core Data stack.
I love the path Apple is taking. The company introduced a number of amazing new features during this year's WWDC, which I plan to cover in the next few weeks.
Questions? Leave them in the comments or reach out to me on Twitter.