Setting up CoreData for SwiftUI

Defining our data model đź› 

In the Project Navigator, you can spot the “To-Do.xcdatamodeld” file Xcode created for us. In this file, we set up and manage the entities of our CoreData data model. In case you are not familiar with the concept of Entities: You can think of an entity as a class, and an attribute, as a property of that class. The only Entity we need for our app is for holding the different To-Do items. Delete the default “Item” Entity by selecting it and pressing the “Delete” key on your keyboard and create a new one by clicking on the large plus button at the bottom. Then, double-click on the created Entity to rename it to “ToDoItem”.



What information do we need for our To-Do items? We need to know the title of the To-Do item (e.g. “Going for a walk”), we need to know when the item was created and whether it has already been completed or is pending.

For this purpose, add an attribute “taskTitle” of the type String to it. To do this, click on the plus button below the attributes section and name it “taskTitle”. Select String as the “Type”. Next, create an attribute “createdAt” of the type Date and a Boolean attribute named “taskDone”.



How CoreData works in SwiftUI

That’s it! We just finished setting up our core data model for holding the items of our To-Do list. Wasn’t that easy? Let’s take a look at how CoreData was implemented into our SwiftUI project by checking the “Use CoreData” box earlier. 

To take a look behind the scenes, open the To_DoApp.swift file. You already know that the App struct especially handles booting up the initial view, which is the ContentView by default. Because we checked “Use CoreData” when creating our project earlier, Xcode created a property called persistenceController and applied an important modifier to the launched ContentView.

Let’s take a look at persistenceController property first.

let persistenceController = PersistenceController.shared

This property is assigned to a PersistenceController. We can find this PersistenceController in the “Persistence.swift” file. The PersistenceController struct contained in this file includes various properties.

Let us briefly review the most important ones. The preview property allows us to use the CoreData functionality in SwiftUI Preview simulators.

Note: Since we have deleted the default “Item” Entity and created a new one called “ToDoItem”, we have to make a quick adjustment here. Delete the existing for-in loop and insert the following loops instead.

static var preview: PersistenceController = {
    //...
    for _ in 0..<3 {
        let newItem = ToDoItem(context: viewContext)
        newItem.createdAt = Date()
        newItem.taskDone = false
        newItem.taskTitle = "Preview Task"
    }
    for _ in 0..<2 {
        let newItem = ToDoItem(context: viewContext)
        newItem.createdAt = Date()
        newItem.taskDone = true
        newItem.taskTitle = "Preview Task"
    }
    //...
}()

The container property is the heart of the PersistenceController, which performs many different operations for us in the background when we store and call data. Most importantly, the container allows us to access the so-called viewContext, which serves as an in-memory scratchpad where objects are created, fetched, updated, deleted, and saved back to the persistent store of the device where the app runs.

The container gets initialized within the PersistenceController‘s init function. In this, the container property gets assigned to an NSPersistentContainer instance. We need to use the name of our “.xcdatamodeld” file, which is “Shared”, as the “name” argument.

init(inMemory: Bool = false) {
    container = NSPersistentContainer(name: "Shared")
    //...
}

Let’s open the To-DoApp file and take a look at the .environment modifier applied to the ContentView.

ContentView()
    .environment(\.managedObjectContext, persistenceController.container.viewContext)

What does this .environment modifier do? Before our ContentView gets launched as the root view, it equips the environment’s managedObjectContext key with the viewContext we just talked about.

The “environment” is where system-wide settings are saved, for instance, Calendar, Locale, ColorScheme, and now, also the viewContext contained in the persistenceController‘s container property. Each of these settings has its own key, in our case, it’s the .managedObjectContext key.

Now, every view in our app can use the viewContext “scratchpad” to retrieve, update, and store objects. We simply need to use the managedObjectContext environment key for accessing it, as you will see later on.

Don’t worry if you are not quite familiar with this. The only thing you need to remember is that we can use the managedObjectContext for fetching and saving our To-Do items. You’ll see how easy this is in a moment.

8 replies on “Setting up CoreData for SwiftUI”

Typo in the pdf file:
“Also, create an attribute createdAt of the type
Data and a boolean attribute called taskDone.”

Should Read:
“Also, create an attribute createdAt of the type
Date and a boolean attribute called taskDone.”

Type “Date” not type “Data”

Unfortunately, as someone mentioned before, with version 12.0.1 of Xcode it is not possible to create a multiplatform app since the ONLY choice is Game, so I am getting so many errors, I am lost. When putting the the first for loops, it says “Cannot find “item” in scope? I may be the only one, sorry. I guess I will just go through the lesson and see what I can pick up. Any suggestions?

Hey Bill, I had the same issue but I went ahead with the lesson anyway and after making the changes to TaskView, the preview worked and all the errors went away.

Core Data, even back in the Objective-C days, has a few quirks. One of which, something Apple has yet to fix, is that often when you add a new Entity (aka a Table) along with its properties (aka Fields) you need to restart Xcode for the newly added entity to get registered in the application.

Leave a Reply

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