You will start by creating a new data model file, then a Swift file that will load the data model.
Download our sample project from here, so you can follow these steps.

See All Source Codes

For 10% OFF - use coupon code ZWV-YJN-TVZ

1) Choose File -> New -> File
On the top right corner, filter all file types by data model, then choose Data Model and click Next.
Keep the file name as-is with the extension .xcdatamodeld, then click Save.

2) Run and Test the project without Core Data

After your run the app on simulator, add a TODO list item and you will notice that it's being added to the list, you can tap it and mark it as complete, but if you kill the app, when you launch it again, it will not have any of the TODO items saved.
In the next step, we will update the Core Data xcdatamodeld to persist these changes.

3) Update the Core Data Model.xcdatamodeld

a) Select the Mode.xcdatamodeld that you created earlier, then click Add Entity. This will create a new entity at the top, just rename that to 'Todo'.

b) Select the Todo entity, and add 2 new attributes:
- taskName and set the type to String
- isCompleted and set the type to Boolean

Now that your Core Data model is ready, we have to write a few lines of code in order load this model.

4) Update your DataManager file

a) Select the DataManager Swift file, and import CoreData
b) Declare the Core Data NSPersistentContainer and pass the model name, in this case it will be Model

You have to add the line 1 and 10

c) Override the init method of your DataManager file, this method will be invoked as soon as this manager class is instantiated.

You have to add the lines 13 to 16

5) Inject the Core Data managedObjectContext in SwiftUI

a) Select the TodoListApp file, this is your @main application file
b) Add the environment modifier and pass the Core Data container view context

You have to add the line 13

6) Add the FetchRequest in SwiftUI view

a) Select the ListContentView file, or any of your SwiftUI views that requires data from Code Data.
b) Add the environment property that was injected in the previous step
c) Create a FetchRequest property that will fetch the Todo entities from Code Data

You have to add the lines 7 and 8

6) Use FetchRequest data instead of DataManager

a) Instead of using 'manager.todoItems' we will use the FetchRequest 'todoItems'. Go ahead and update the following instances where the manager's todoItems are being used.

Update the lines 10, 11 and you can remove line 15

- Line 10 used to access the todoItems from the manager, so we no longer need to do that, because the FetchRequest has a list of items from Core Data.
- Line 11 changed so the todo task name will display 'No Name' by default, in case the data from FetchRequest happens to have nil as the name.
- Line 15 used to force the view to update, but that's not necessary, because the FetchRequest will take care of that, whenever we update todo item.

7) Save new items to Core Data

a) In the same SwiftUI view file, we will update the 'addItem' method, so we can save the todo task into Core Data instead of using the DataManager. See the code changes required below.

Remove line 9 and add lines 10 to 12

- Line 9 used to save a new todoItem in memory using the DataManager object.
- Line 10 will create a new Todo entity using the viewContext that was injected earlier.
- Line 11 will set the name for the new Todo entity, then next line of code we will save this Todo task/entity into Core Data

You've done a great job so far! Run the app and test it.


Q) When I mark a task as completed, then launch the app next time, it shows un-completed. Why is that?
A) Whenever you make a change to any of the FetchRequest items, you must invoke the save() method. Here is something that you can update in your code, in the same ListContentView SwiftUI view.

See line 15, where you save any changes into Core Data

Q) Where can I get the full source code for this tutorial?
A) We always encourage our customers and visitors to follow the tutorial first, so they can learn what each step has to offer and how the code works. Here is the download link to the full source code, with all the changes from this tutorial.

If you have any questions or suggestions, please feel free to send an email to
Thanks for reading!