Core Data: Fundamentals

Jul 19 2022 · Swift 5.5, iOS 15.4, Xcode 13.3.1

Part 1: The Core Data Stack

06. Setting Up the Stack

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 05. Persistent Store Coordinator Next episode: 07. Conclusion

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Transcript: 06. Setting Up the Stack

Now that you have a better understanding of the moving parts let’s actually write some code.

Download the starter file for this project and let’s jump right in. The project contains some of the UI work already done to get you up and running.

Build and run the app. You should see nothing remotely close to a rocket launch app. Don’t worry you’ll get there. For now, there’s a list of placeholder data along with a button at the bottom to create a new launch. If you tap it a modal pops up where you can add details about your new launch and hit save.

At the moment the save button doesn’t do anything and the goal here is to get rid of the mock data and insert real launches that you persist to the data store. Before you can do that you need to create the Core Data stack.

The first thing you’re going to do is add a data model to your project. Right click on the RocketLaunches group and select New File.

Scroll down until you find the Core Data section. Select the Data Model and hit Next.

Name it “RocketLaunches” and hit create.

You should see a file added to your project named RocketLaunches.xcdatamodeld. This file represents the data model in your app. If you click on it you’ll see that it’s a visual editor that allows you to define entities. When you learned about managed object models you learned that Core Data handles creating the underlying data containers for you and you work through an editor - this is that editor. Don’t worry, you’ll get to all of this in a second; for now that’s all you need to do.

Now that you have the data model, you can create the rest of your stack using the NSPersistentContainer class. If you used the Xcode template that had Core Data built in when creating the project, you would get the RocketLaunches.xcdatamodeld and NSPersistentContainer class files for free. So let’s try to duplicate what you would get from that template.

Right click on the “Model” group and choose New File and then Swift File and name it Persistence.swift

At the top of the file, after the copyright notice, go ahead and import the Core Data framework so that you can use all its related classes.

import CoreData

Create a struct called PersistenceController:

struct PersistenceController {

}

Setup two static properties: one for a shared PersistenceController and another for a preview PersistenceController.

struct PersistenceController {
  static let shared = PersistenceController()

  static var preview: PersistenceController = {
    let result = PersistenceController(inMemory: true)
    let viewContext = result.container.viewContext
    
    // Dummy data will go here later
    
    do {
      try viewContext.save()
    } catch {
      let nsError = error as NSError
      fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
    }
    return result
  }()
}

You use the shared property to access the context while running the app. The preview context, once populated, will allow you to load dummy data into the Preview Canvas in Xcode so you can see how your data looks.

Next, after the preview property, add the persistent container as a property, and declare the init method.

  let container: NSPersistentContainer

  init(inMemory: Bool = false) {

	}  

The NSPersistentContainer class is a fairly simple class. Given a data model, which you just created, it creates the underlying managed object model, the managed object context, and the persistent store coordinator for you.

Inside the init method, create an instance of a persistent container.

let container = NSPersistentContainer

The initializer for this class takes a name, which sets the name of the persistent store. It’s also used to look up the name of the NSManagedObjectModel object used with the NSPersistentContainer object. Since you named the data model “RocketLaunches”, by providing the same name for the persistent container you’re ensuring that the managed object model will use the models you define in the xcdatamodeld file.

container = NSPersistentContainer(name: "RocketLaunches")

Then add an if statement to check if you’re dealing with an in-memory instance of the PersistenceController. If so, set the container’s persistent store description url to /dev/null:

if inMemory {
  // swiftlint:disable:next force_unwrapping
  container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}

The only thing left to do now is to complete the creation of the Core Data stack by calling the loadPersistentStores method.

container.loadPersistentStores { _, error in }

The method takes a completion block with two arguments - an instance of NSPersistentStoreDescription which is an object that allows you to customize, create and load the underlying store, and an Error value if the creation of the stack failed.

You won’t be doing any customizing so you can ignore that first argument. In the event that there’s an error, for the sake of simplicity you can go ahead and log the error and crash app.

if let error = error as NSError? {
  fatalError("Unresolved error \(error), \(error.userInfo)")
}

Lastly, setup properties on the view context to help later on when you work with Core Data asynchronously.

  container.viewContext.automaticallyMergesChangesFromParent =
    true

  container.viewContext.name = "viewContext"
  /// - Tag: viewContextMergePolicy
  container.viewContext.mergePolicy = 
    NSMergeByPropertyObjectTrumpMergePolicy
  container.viewContext.undoManager = nil
  container.viewContext.shouldDeleteInaccessibleFaults = true

These properties help define some rules when merging data from various threads, and also gives the viewContext a name, which will help differentiate it from others you’ll create later on.

You should know that moving forward, for your own projects, adding the code you just added is as simple as checking the “Use Core Data” checkbox when creating a new project. Both the data model file and the Peristence.swift file is automatically added for you.

Before putting this to use, let’s review everything you learned in the next video.