Relational Core Data with MVVM in iOS App

Minawati
5 min readAug 5, 2022

--

Goally is an iOS app that I created to help us stay motivated when learning, where we can set a list of learning goals and tasks with a reminder, track the learning progress, and also get an achievement whenever we achieve a certain goal.

To develop this application, especially list goals and tasks features, I’m using Relational Core Data with MVVM architecture. I’m using Core Data to persist the data on the local storage and MVVM architecture to separate the view model (application logic) from the view, which makes the code more reusable and cleaner. But when developing this application, I had a hard time finding the resources that cover Relational Core Data with MVVM. That’s why I want to share my knowledge about this topic. Let’s get started!

So how do we implement Core Data in our project?

First, we will create a new project. Don’t forget to check the Use Core Data checkbox.

Create new project

After the project is loaded, you can go to the Navigator Panel on your left and find a xcdatamodeld & persistence file. Those two files will be automatically generated when we check the Use Core Data checkbox.

Tips: Make sure your xcdatamodeld file name is not the same as your project name.

After creating a new project, let’s go to the xcdatamodeld file and add a new entity called “Goals” and “Tasks”. These two entities will have their own attributes. You can also add new attributes and set their type according to your needs.

As the Goals Entity will have a one to many relationship with the Tasks Entity, we have to create a relationship between them. To create a relationship, we can just add a relationship and define its destination and inverse to both entities.

Goals entity, attributes, and relationship
Tasks entity, attributes, and relationship

To specify and tell Core Data that this is one to many relationship, we have to go to the Inspector Panel on right and change the relationship type. For the goal relationship, we change the type to “to one” and for the tasks, we change the type to “to many”.

Change relationship type

Besides that, don’t forget to change the Codegen to Manual/None. By changing the Codegen to Manual/None, we will have to create and maintain our class & properties manually.

Change the codegen

To generate the class and properties file, we have to go to the Editor and choose the Create NSManagedObject Subclass. Select the data model and the entities that you want to manage. In this case, you can just select them all. After that, we can just create it.

Create NSManagedObject Subclass

That’s all for the Data Model! Now let’s move into the code. First of all, let’s create a file called CoreDataManager. CoreDataManager class will be in charge of the Core Data Stack of the application, where we can set up the persistent container and viewcontext of our application.

The persistent container is used for handling the creation of the managed model, persistent store coordinator, and the managed context. Meanwhile, viewcontext is used to track changes to instances of our application types, where the changes to managed objects will remain in memory on the associated context until Core Data saves that context to the persistent stores.

We can also fetch, add, and delete the data on the Core Data. All of those functions will be handled by Core Data Manager. Below is the code to fetch, add, and delete the Goals.

And then, how to fetch, add, and delete the Tasks? Well, it’s the same as the Goals, you can just change the object model parameter to Tasks for the fetch and delete function. But there’s a slight difference when we want to add a new task, where we have to use the accessors to add the Tasks to the Goals. The accessors itself is automatically generated when we create NSManagedObject Subclass.

Accessors for Tasks

That’s all for the CoreDataManager! Now we can move to the ViewModel. Let’s create a file called GoalListViewModel and TaskListViewModel. Those ViewModel will handle all the logic needed for the GoalList and TaskList feature, where it will be associated with CoreDataManager to use the function. Don’t forget to reload the data by calling getAllGoals() function.

That’s all for the ViewModel, but how do we use the ViewModel in our View?

First of all, you must inject your managed object context into the SwiftUI environment by adding the code below to your Scene Delegate. Make sure you are using viewContext from the CoreDataManager.

ContentView().environment(\.managedObjectContext, CoreDataManager.shared.viewContext)

Tips: Make sure you access the same viewcontext throughout your application.

After that, we can just create a new variable called goalListViewModel with the property wrapper StateObject to instantiate ObservableObject — GoalListViewModel.

@StateObject private var goalListViewModel = GoalListViewModel()

And then, you can just use this variable to call for the function on the GoalListViewModel. For example, you want to delete a goal. Then you can just use it like the code below.

goalListViewModel.deleteGoal(goal: selectedGoal)
Goally — Delete Goal Simulation

That’s all for this topic. If there is any feedback, feel free to leave it in the comment section.

Thank you!

--

--