0% found this document useful (0 votes)
17 views76 pages

Core Data Quick Start in SwiftUI

The document is a guide for SwiftUI developers on using Core Data, providing an overview of key concepts and components such as data models, NSPersistentContainer, and NSManagedObjectContext. It includes acknowledgments, book conventions, and a structured approach to understanding how to manage data within SwiftUI applications. The content is designed to help developers effectively utilize Core Data for persistent data storage in their apps.

Uploaded by

vixoto5989
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views76 pages

Core Data Quick Start in SwiftUI

The document is a guide for SwiftUI developers on using Core Data, providing an overview of key concepts and components such as data models, NSPersistentContainer, and NSManagedObjectContext. It includes acknowledgments, book conventions, and a structured approach to understanding how to manage data within SwiftUI applications. The content is designed to help developers effectively utilize Core Data for persistent data storage in their apps.

Uploaded by

vixoto5989
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 76

VISUAL TIME-SAVING REFERENCE

Core Data Quick Start


iOS 16

In SwiftUI
[Brief introductory description of what this chapter contains.]

Mark Moeykens
www.bigmountainstudio.com A CORE DATA REFERENCE GUIDE
1 FOR SWIFTUI DEVELOPERS BigCoreMountain
Data Quick StartStudio
in SwiftUI
Version: 22-JUNE-2022
©2021 Big Mountain Studio LLC - All Rights Reserved

www.bigmountainstudio.com 2 Core Data Quick Start in SwiftUI


ACKNOWLEDGEMENTS
Writing a book while also working a full-time job takes time away from Many other developers also proof-read and gave feedback on the book.
family and friends. So first of all, I would like to thank my wife These include: Stewart Lynch, Waleed Alware, Antti Juustila, Chris
Gambrell, Jahns Hendrik, Terrance McHugh, Gerard Gomez, Berkant
Jaqueline and daughter Paola for their patience and support. Dursan, Darius Dunlap, Robert DeLaurentis, Jake Steramma, and Inal Gotov.

Next, I would like thank Chris Ching who finally convinced me to learn And finally, I would like to thank the creators of all the other sources of
information, whether Swift or Core Data, that really helped me out and
Core Data and instructed me on this topic.
enabled me to write this book. That includes Apple and their documentation
and definition files, Donny Wals, Antoine van der Lee, Paul Hudson, and
I would also like to thank my friends who always gave me constant Mohammad Azam.
feedback, support, and business guidance: Chris Ching, Scott Smith,
Rod Liberal, Chase Blumenthal and Chris Durtschi.

I would also like to thank the Utah developer community for their
help in making this book possible. This includes Dave DeLong and
Andrew Madsen.

www.bigmountainstudio.com 3 Core Data Quick Start in SwiftUI


Table of Contents
The table of contents should be built into your EPUB and PDF readers. Examples:

Books App Adobe Acrobat Reader Preview

www.bigmountainstudio.com 4 Core Data Quick Start in SwiftUI


BOOK CONVENTIONS
Book Conventions

Custom Xcode Editor Theme

I created a code editor color theme for a high-contrast light mode. This is the theme I use for the code throughout this book.

If you like this color theme and would like to use it in your Xcode then you can find it on my GitHub as a gist here.

💡
If you download the theme from the gist, look at
the first line (comment) for where to put it so
Xcode can see it.

If the directory does not exist, then you will have


to create it.

www.bigmountainstudio.com 6 Core Data Quick Start in SwiftUI


Book Conventions

Embedded Videos

The ePUB version of the book supports embedded videos.

The PDF version does not.

This icon indicates that this is a playable video


in the ePUB format.

But in PDF it renders as simply a screenshot.

💡
In some ePUB readers, including Apple Books, you
might have to tap TWICE (2) to play the video.

www.bigmountainstudio.com 7 Core Data Quick Start in SwiftUI


CORE DATA CONCEPTS

There are similar patterns that can be found when you have applications working with data.
Core Data is no different.
First, you will learn some concepts. No code in this chapter.
Then you will learn what Apple calls each of these parts in the Core Data framework. In the end, you will be able to THINK with Core Data
concepts.
Core Data Concepts

The Flow
Let’s go over the 4 main components used to work with Core Data in SwiftUI. You will learn the real names and purposes behind these concepts.
We won’t get too technical. This chapter will give you a good overview of the pieces that make up Core Data and how to think with it.

Data Structure The Toolbox The Playground The View

The place where data can


Contains the tools you The place that requests
Where your data is be changed, updated,
need to prepare and data and enables users to
described. deleted or undo those
handle your data. work with that data.
changes.

1 2 3 4

www.bigmountainstudio.com 9 Core Data Mastery in SwiftUI


Core Data Concepts

1. Data Model

The first part of the flow is the data model. You will learn what a data model is (and what it is not).

www.bigmountainstudio.com 10 Core Data Mastery in SwiftUI


Core Data Concepts

Data Models - The First Part


The first part is what is called the “Data Model”. A data model tells Core Data what the data looks like.

Data Model The Toolbox The Playground The View

2 3 4

www.bigmountainstudio.com 11 Core Data Mastery in SwiftUI


Core Data Concepts

Data Models
struct Person { This defines a You have probably created a
let name: String data model but struct or a class to hold data.
let age: Int there is no actual
} data in it. These classes and structs are
called data models.
struct DataModels: View {
@State private var name = "" Data models are populated with
@State private var age = 0 values and used in some way.

var body: some View {


VStack {
TextField("Name", text: $name)
TextField("Age", value: $age, format: .number)
Use width: 214
Button("Save") {
let newPerson = Person(name: name, age: age) Core Data needs to know how to
store a Person object.
// Save data object somewhere
} You need to define your data
} models in a special way before
.textFieldStyle(.roundedBorder) working with them in Core Data.
.padding()
.font(.title)
}
}

www.bigmountainstudio.com 12 Core Data Mastery in SwiftUI


Core Data Concepts

Data Models or Data Objects?


Let’s clear up the difference between “data model” and “data object”.

Data Model Data Object

The model is the definition of how data will be structured The object is an instance of the model that is populated
or organized. It defines property names and types. It can be with data. For example, the newPerson variable here is
a struct or a class. an object:

struct Person {
let name: String let newPerson = Person(name: name, age: age)
let age: Int
}

💡
Core Data can’t use the Person struct as it is
defined here. You will have to define it a different
way. See next page.

www.bigmountainstudio.com 13 Core Data Mastery in SwiftUI


Core Data Concepts

Define Your Data Models

You define your data model descriptions in a special “Data


Model” file that Core Data uses.

This helps Core Data understand how you want your data
structured.

This book will walk you through how to use this and set it up. The data model

💡
Think of “Attribute” as “property”.
This file just holds the definition of objects, like property
names and their types (string, bool, etc). The purple icons just represent the
data types specified.
It doesn’t actually hold any values.
N = Number
This will actually replace the Person struct on the previous S = String
page.

www.bigmountainstudio.com 14 Core Data Mastery in SwiftUI


Core Data Concepts

Part 1 in The Flow: Data Model


So the first thing you need is a data model so Core Data knows the structure of your data, properties, types, etc.

Data Model ? ? The View

Now that Core Data


knows what the data will
look like, it needs tools
to read and store the
values.

2 3 4
Person
name: String
age: Int

Remember, these are


just models, no data
objects/values are in
here.

www.bigmountainstudio.com 15 Core Data Mastery in SwiftUI


Core Data Concepts

2. Tools for Persistence

When your app has data, you have to store it someplace where it can persist so when the app is closed or if the device loses power it won’t
disappear. This chapter talks about the subject of persistence.

www.bigmountainstudio.com 16 Core Data Mastery in SwiftUI


Core Data Concepts

The Toolbox - The Second Part


“Persist” means “to continue to survive or exist”. If you close your app or turn your phone off, the data will survive.
The second part, the toolbox, has to do with tools to read your data model and with this knowledge it can retrieve and persist your data.

Data Model The Toolbox The Playground The View

Reads Model

3 4

www.bigmountainstudio.com 17 Core Data Mastery in SwiftUI


Core Data Concepts

Persistent Storage
When an app saves data it will store it somewhere so that data can then persist, even when the power is turned off or the app is closed.

Apps on your iPhone are stored so they can persist if your phone loses all power. All iPhones have a physical component that can store apps and data.

A storage
Storage with Power device a solid Storage with no Power
state drive
(SSD).

Data Data Data Data Data Data


Data Data Data Data Data Data
Data Data Data Data Data Data
Data Data Data Data Data Data

The data still persists.

💡 Core Data will store values to the physical storage on the device so it can persist after closing the app or shutting off the device.

www.bigmountainstudio.com 18 Core Data Mastery in SwiftUI


Core Data Concepts

NSPersistentContainer
Core Data uses the NSPersistentContainer to store data so it persists on the device. This IS the toolbox. The NSPersistentContainer has quite a few
tools we can use.

NSPersistentContainer Persistent Storage

The NSPersistentContainer:
• Reads your Data Model and sets it up
for use
• Controls where your data is persisted
on the device
Store data Data Data • Is responsible for loading up your
Data data from the persistent storage so
Data
your app can use it

💡
Note: NS stands for “Next Step” (NeXTSTEP) which was an
operating system that Apple bought in 1996 and became the
foundation of macOS in 2000. Yeah, it’s old. But it’s continually
being worked on.

www.bigmountainstudio.com 19 Core Data Mastery in SwiftUI


Core Data Concepts

Container
Think of a container as a box that can hold many things. A container can hold tools, food, pencils, etc.
In programming, containers can hold a collection of other objects.
The NSPersistentContainer is like a toolbox (container) that will provide you with almost every tool you might need to work with Core Data.

NSPersistentContainer Tools that create a


Tools to load your space for you to
data model. change your data
before saving it.

Tools to read and Tools for working


write your data to with mock data for
persistent storage. previews in SwiftUI.

💡
Many of these tools were separate. Developers had to do a lot of setup work to make them all work
together in the past.

But Apple developers made Core Data way easier to use with the NSPersistentContainer.

www.bigmountainstudio.com 20 Core Data Mastery in SwiftUI


Core Data Concepts

Data Model + Data Values = Data Objects


Your data model and the actual data values are two separate files. The persistent container and its toolbox will “merge” the two together. It always gives
you the data, as defined in your data model, so you have data objects you can now display and work with.

Data Objects
Data Model
Describes what the data will Person
class Person {
look like.
name String var name = “Natasha”
var age = 34
age Int
}

class Person {
var name = “Mark”
var age = 51
}

Data Values
Actual values
name age
💡
Why isn’t this part in the flow?
Natasha 34 I intentionally left out the data values from the flow because you don’t
Mark 51 have to do anything to get it working.

www.bigmountainstudio.com 21 Core Data Quick Start in SwiftUI


Core Data Concepts

Part 2 in The Flow: NSPersistentContainer


When you start your app, one of the first things you want to do is instantiate your NSPersistentContainer so it can read data model and then your
persisted data and get it ready.

Data Model NSPersistentContainer ? The View

Now for the next part.

This is where data


object changes are
managed.

Data
Reads Model
Data

3 4
Person Data
name: String Data
age: Int

The data on the device


will be loaded up and
ready for the next step.

www.bigmountainstudio.com 22 Core Data Mastery in SwiftUI


Core Data Concepts

3. Managing Data Objects

Once Core Data understands the data models and where the data is stored, it can retrieve and give data objects to your app.

At the end of this section, you will understand more about how and where data objects are managed.

www.bigmountainstudio.com 23 Core Data Mastery in SwiftUI


Core Data Concepts

The Playground - The Third Part


We need a playground where we can play with data. Many times, after fetching data, you enable the user to insert new data, change the data, delete the
data, or maybe undo changes. This is where your users will do it, where the data objects (the things with actual values) are managed.

Data Model NSPersistentContainer The Playground The View

Reads model Provide data

Save changes

www.bigmountainstudio.com 24 Core Data Mastery in SwiftUI


Core Data Concepts

Memory
When any application works with data or data objects, it is usually done in memory or RAM. “RAM” is short for “random access memory”.

Think of RAM or memory as temporary. If the device loses power, all the data that is in memory is gone.

The operating system gives your app memory to work within. When you close the app, the operating system reclaims it and any data within is gone.

Memory with Power Memory with no Power

Data Data Data


Data Data Data
Data Data Data
Data Data Data
Any data in memory will disappear.

Core Data will use memory to temporarily store data changes. This is useful in case the user changes their mind and decides not to
💡 save or delete data (undo).
It’s also useful because memory is super fast.

www.bigmountainstudio.com 25 Core Data Mastery in SwiftUI


Core Data Concepts

NSManagedObjectContext
Core Data uses the NSManagedObjectContext as a space to let you freely change data in memory. It is where updates, deletions, and the creation of
new data objects take place.

You manage objects here. (Remember, data objects are data models that have values.)

NSManagedObjectContext
(In Memory)
The NSManagedObjectContext:
• Enables you to fetch specific data
objects from persistent storage
• Manages object changes in memory
until written to the persistent store
• Allows you to undo changes
• Has the ability to perform data object
work in the background
Fetched Data
Changed Data
Deleted Data
New Data 💡
All of these data object changes are just in memory.

You will have to call a function to have NSPersistentContainer


commit (save) the changes to the persistent store.

www.bigmountainstudio.com 26 Core Data Mastery in SwiftUI


Core Data Concepts

Managed Object…”Context”
The word context means “everything related to some event, or idea so you can make sense with what is being said or shown”.

When you have data objects in memory, the operating system has to know what this memory is related to. Is it for App A or App B?

So context lets people and computers know how the things in memory are connected with which app and what they are used for. One app can have
many contexts being used for different purposes.

iPhone Memory

App A Context App B Context

Data Context If your app is going Drawing Context If your app works with
to work with data drawing graphics, it will
objects, it will need need some space in
some space in memory memory to work with that
to work with that data. drawing data.

So the context just So the context just


means this data is means this drawing data
related to this app. is related to this app.

Note: There are many contexts for many frameworks and technologies within the available libraries used for developing apps.
💡 Here, you see examples of data and drawing contexts. When you see “context”, think “space in memory to work within”.

www.bigmountainstudio.com 27 Core Data Mastery in SwiftUI


Core Data Concepts

NSManagedObjectContext is from the NSPersistentContainer


The NSManagedObjectContext is one of the tools provided to you from the NSPersistentContainer.

I will give you a place in memory (context) where you can make all of your data
object changes.

Let me know when you are done and I will save all your changes to the store.

NSPersistentContainer NSManagedObjectContext

www.bigmountainstudio.com 28 Core Data Mastery in SwiftUI


Core Data Concepts

Part 3 in The Flow: NSManagedObjectContext


The NSManagedObjectContext is provided to you by the NSPersistentContainer. It’s giving you a space in memory (context) to work with your data
objects before committing it (saving it) to persistent storage.

Data Model NSPersistentContainer NSManagedObjectContext The View

The view will fetch data,


allow users to edit,
delete and insert new
data.

Data Data
Reads model Data Provide data Data
Data Data

4
Person
name: String
Changed Data Changed Data
age: Int Deleted Data
Deleted Data Save changes
New Data New Data

This is memory space to


work with data changes.

www.bigmountainstudio.com 29 Core Data Mastery in SwiftUI


Core Data Concepts

Managed Object Context and Data Flow


The NSManagedObjectContext is not automatically filled up with all the data from your persistent store. Think of it as a temporary place where you can
fetch, create, change and destroy things within it. So only when requested will the persistent container load data into the managed object context.

NSPersistentContainer NSManagedObjectContext The View

2 1
Fetch data I need data
Mark 51
Data is loaded when
requested from the view.
Jaque 42
3 4
“Mark”, 51 “Mark”, 51
Load data Display data Chase 34
“Jaque”, 41 “Jaque”, 41
“Chase”, 34 “Chase”, 34
Paola 28

“Mark”, 51 6 “Mark”, 51 5
“Jaque”, 42 “Jaque”, 42
Persist data Save data Save
“Paola”, 28 “Paola”, 28

www.bigmountainstudio.com 30 Core Data Quick Start in SwiftUI


Core Data Concepts

4. The View

When your app starts there is a particular order in which it initializes Core Data for use.

You will learn this order and the idea of how views work with Core Data in this section.

www.bigmountainstudio.com 31 Core Data Mastery in SwiftUI


Core Data Concepts

Loading Core Data


The last piece of the puzzle is the app itself. When the app starts, it will create the NSPersistentContainer first. This is a simplified idea of how it all
works so you can think with it. You will learn more details about each of these parts in this book.

The App
2 3

The NSPersistentContainer is created. The Data Model + Data Values are read.

The App starts.

4 5
“Mark, 51
“Paola”, 18

Data objects (values) are created by the


The NSPersistentContainer offers an persistent container and loaded into
NSManagedObjectContext to work in. memory when fetched.

www.bigmountainstudio.com 32 Core Data Mastery in SwiftUI


Core Data Concepts

Using @Environment
A common practice in SwiftUI apps is to store the
Environment NSManagedObjectContext in the environment.
This way it is available to all views so you can fetch and save
data. The View

SwiftUI has some super easy ways to get


data and display it.

Use width: 214

Data Data
Data Data Saving your changes is also super easy.

www.bigmountainstudio.com 33 Core Data Mastery in SwiftUI


Core Data Concepts

Summary

You’ve learned a lot of concepts around Core Data. You’ll be using these concepts all throughout the book. So let’s summarize them.

www.bigmountainstudio.com 34 Core Data Mastery in SwiftUI


Core Data Concepts

The Main Part of Core Data


If you were to ask me what is the main part that makes Core Data work, I would say it is the NSPersistentContainer. Everything you do in Core Data
revolves around this one main part. Over the years, Apple has made this the Core Data central toolbox for everything you need.

Data Model NSPersistentContainer NSManagedObjectContext The View

Stores Data

Provides a place to
Reads Model change data

www.bigmountainstudio.com 35 Core Data Mastery in SwiftUI


Core Data Concepts

The Flow
Each of the 4 parts all have their own responsibilities.

Data Model NSPersistentContainer NSManagedObjectContext The View

This space (context) is The app will create the


used to manage your NSPersistentContainer
The persistent container data objects. and load data from the
Use the Data Model to will read your data persistent store.
describe what your data model and then load It will track changes,
looks like. your data from the deletions, insertions, The views will access
persistent store. etc. the managed object
context from a central
It provides you the tools place.
to undo or commit your
changes to the
persistent store.

www.bigmountainstudio.com 36 Core Data Mastery in SwiftUI


FIRST EXAMPLE

In the previous pages, you learned about the 3 main tools the app needs to work with Core Data. You should have a pretty good concept of
what they are and how the app uses them.

Now you’re going to learn what those concepts look like in code as we set up a data model, add some data and show it in a SwiftUI view.
First Example

1. Setting Up the Data Model

By the end of this section, you will learn the basics of creating and setting up a data model in Xcode.

www.bigmountainstudio.com 38 Core Data Mastery in SwiftUI


First Example

New or Existing Project?


This example will take you through creating your first example with Core Data. You can use it on an existing project or a new project.

If you create a new project,


uncheck the “Use Core
Data” option.

This option will


autogenerate a lot of code
that can be confusing when
first starting out.

We’re going to make it very


simple.

www.bigmountainstudio.com 39 Core Data Mastery in SwiftUI


First Example

Create a New Data Model

When you add a new file to your Xcode


project you will want to scroll down to the
Core Data section and select Data Model.

www.bigmountainstudio.com 40 Core Data Mastery in SwiftUI


First Example

The Data Model Name

On the next screen, give the data


model any name you want.

Let’s break down the file extension.

xc - Xcode

datamodel - You know from the


previous chapter that a data model just
describes what the data looks like. It’s
not actual data values or data objects.

d - Yes, there is a “d” at the end. What


is this for? It stands for “directory”. The
directory is structured like this:

- FirstExample.xcdatamodeld
- FirstExample.xcdatamodel (no “d”)
- contents

The contents file is an XML file


representation of the data model.

www.bigmountainstudio.com 41 Core Data Mastery in SwiftUI


First Example

Data Model Editor

We’re going to recreate this data


model which you saw earlier using the
editor:
struct Person {
let name: String
let age: Int 2
}

4
1. Click the Add Entity button
2. Give your entity a name
3. Click the + button in the Attributes 3
section
4. Add a name and assign a type

1
💡
The editor will force you to make the
first letter in entity names uppercase.
?
It will also force you to make attribute
names start with a lowercase letter. Can I change the position of attribute names?

Think of entities as classes and No, they are sorted alphabetically. Sometimes you will notice they are in random order when you first
attributes as properties. add them. But if you close this file and open it again, the attributes are sorted alphabetically again.

www.bigmountainstudio.com 42 Core Data Mastery in SwiftUI


First Example

Attribute Types

You probably noticed that the available Attribute Type Swift Type General Information
attribute types didn’t have a plain Int as Binary Data Data When you want to store images, videos, sound files, or any other
we used in our struct. data objects
Boolean Bool True or false
Numbers can be broken down into how
Date Date Dates and times
big the number can get or the range of
values they offer. Decimal Decimal Highest level of precision. Great for currencies.

Double Double More precise than a Float (at least 15 decimal places)
This table will help you decide which
types to use. Float Float A number with a decimal when you don’t need the greatest precision

Integer 16 Int16 When you need a smaller number


(-32,768 to 32,767)

Integer 32 Int32, Int When you need a bigger number range


(-2,147,483,648 to 2,147,483,647)

Integer 64 Int64, Int For HUGE numbers


(-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)
💡 String String Text

Transformable NSObject When no other type will do


Note: A Swift Int type can be Int32 or
Int64 based on whether the platform is a Undefined Default type that will give you an error to remind you to set a defined
32 or 64-bit system. That’s why you see it type
next to both Int32 and Int64. (Most are URI URL Web, file, or any other URL formats
64-bit now.) UUID UUID When you need a unique identifier (id)

www.bigmountainstudio.com 43 Core Data Mastery in SwiftUI


First Example

First Step Done


You added a data model file to your project and added an entity with some properties (attributes). Step one is now complete.

1. Data Model 2. NSPersistentContainer 3. NSManagedObjectContext 4. The View

Stores Data

Provides a place to
Reads Model change data

www.bigmountainstudio.com 44 Core Data Mastery in SwiftUI


First Example

2. The Persistent Container

It is time to set up your persistent container.

A common practice is to create your persistent container when your app starts or when you first need the data.

And you probably want to keep it alive for the life of your app (or the life of the views that need it) so you don’t have to keep creating it.

www.bigmountainstudio.com 45 Core Data Mastery in SwiftUI


First Example

The Persistent Container


Starting as simple as possible, the only responsibility of this class will be to create our persistent container.

import CoreData
When the persistent container is created, it needs the name of the data
class FirstExampleContainer { model to read.
The name should be exactly the same name as the file name.
let persistentContainer: NSPersistentContainer

init() {

persistentContainer = NSPersistentContainer(name: "FirstExample")

persistentContainer.loadPersistentStores { _, _ in }

}
Xcode Project Navigator
}

Now that the persistent container knows what the data should look like, we can load
the persistent stores where the data exists.

It knows exactly where to look and get it.

The closure and the parameter names are intentionally left blank. This is where you
check for and handle any errors. We will cover this later in the book.

www.bigmountainstudio.com 46 Core Data Mastery in SwiftUI


First Example

2 Steps Done
We have our data model defined and we created our persistent container. The next step is to set up the managed object context in a way that our views
can use it.

1. Data Model 2. NSPersistentContainer 3. NSManagedObjectContext 4. The View

Stores Data

Provides a place to
Reads Model
change data

www.bigmountainstudio.com 47 Core Data Mastery in SwiftUI


First Example

3. The Managed
Object Context

We need to set up a space in memory (context) to manage our data objects. SwiftUI has a really easy way in which we can do this.

www.bigmountainstudio.com 48 Core Data Mastery in SwiftUI


First Example

Managed Object Context Environment


In your project’s App file, you will want to use the environment modifier on your view to attach the managed object context.

import SwiftUI
The environment modifier provides a special
Remember, persistentContainer is the property
property just for your managed object
@main we created to hold our NSPersistentContainer.
context.
struct SwiftUI_CoreDataApp: App {
var body: some Scene {
WindowGroup { Persistent
FirstExampleView() containers give us
.environment(\.managedObjectContext, FirstExampleContainer().persistentContainer.viewContext) a managed object
}
context
(playground in
}
memory) to make
}
changes to data.

💡 💡
Note: The way environment modifiers work is they make an object
available to the view it is attached to AND all child views from there. More Info: If you want to learn more about how the environment
This provides views with a way to fetch data, make changes, and works, take a look at the Environment chapter in the “Working with
save data. Data in SwiftUI” book.

www.bigmountainstudio.com 49 Core Data Mastery in SwiftUI


First Example

3 Steps Done
The persistent container is created and the viewContext (managed object context) is added to the environment. Now the view has to access the
managed object context so it can get some data and display it on the screen.

1. Data Model 2. NSPersistentContainer 3. NSManagedObjectContext 4. The View

Stores Data

Provides a place to
Reads Model
change data

www.bigmountainstudio.com 50 Core Data Mastery in SwiftUI


First Example

4. The View

With Core Data set up, it is now time to start working with data objects.

www.bigmountainstudio.com 51 Core Data Mastery in SwiftUI


First Example

@FetchRequest Concept
The view is going to use a property wrapper called @FetchRequest to retrieve data from the managed object context. The request is passed from the
view to the managed object context.

NSManagedObjectContext The View

@FetchRequest
“I need data.”

The request is passed on to the


persistent store and loads the
context with the data requested:

But even this diagram is not


⚠ entirely accurate…

www.bigmountainstudio.com 52 Core Data Mastery in SwiftUI


First Example

@FetchRequest Pipeline Concept


The previous diagram gives you the idea a fetch is made, data is returned and that is it. But really, when the @FetchRequest is used it is almost setting
up a pipeline. So whenever data changes in the managed object context the view automatically gets updated.

NSManagedObjectContext The View

@FetchRequest
“I need data.”

The request is passed on to the


persistent store and loads the
context with the data requested:

Now, whenever the data in the managed object


context changes, those changes are automatically
sent down the pipeline and the view is updated.

www.bigmountainstudio.com 53 Core Data Mastery in SwiftUI


First Example

@FetchRequest
Here’s your first view using Core Data. It’s not very exciting. We will add data on the next page.

struct FirstExampleView: View {


@FetchRequest(sortDescriptors: []) private var people: FetchedResults<PersonEntity>

var body: some View {


VStack {
List(people) { person in
Text(person.name ?? "")
}
}
.font(.title) The @FetchRequest property
} wrapper sets up that pipeline to the
There
Use is no
width: 214 } managed object context.
data added
yet. 💡 sortDescriptors - This will sort the
data that you get back in the way you
What’s amazing about this code is: specify. It is an array, meaning you can
provide many sorting options. It’s left
• Xcode synthesized (autogenerated) that
blank so the data will be unsorted.
PersonEntity class for you just by looking at
the Data Model. Autocomplete works with it.
FetchedResults - This is the
• The type you set on FetchedResults collection of your data objects that
(PersonEntity) is literally all you have to do so were retrieved from the store. Notice it
Core Data knows what data you want. It’s that is generic so you set the type of data
simple! you want returned within the brackets.

www.bigmountainstudio.com 54 Core Data Mastery in SwiftUI


First Example

No ID?
How come there is no id specified for the List view?

struct FirstExampleView: View {


@FetchRequest(sortDescriptors: []) private var people: FetchedResults<PersonEntity>

var body: some View {


VStack { 💡
List(people) { person in
Text(person.name ?? "")
} When you use List, you sometimes
} have to specify a key path to an id.
.font(.title)
There is no } You have probably seen code similar
Use width:
data added214 } to this before:
yet.

List(people, id: \.self)

The person’s name is an optional string. You don’t have to do this if your items
Core Data defaults many of the types to conform to Identifiable though.
optionals.
The good news is Core Data
One way to handle this is with a nil coalescing automatically makes your entities
operator (??). conform to Identifiable for you so
you will never have to specify the id.

www.bigmountainstudio.com 55 Core Data Quick Start in SwiftUI


First Example

@Environment for Managed Object Context


We need to reference the managed object context now. We added it to the environment so we will need
the @Environment property wrapper to access it.

struct FirstExampleView: View {


@FetchRequest(sortDescriptors: []) private var people: FetchedResults<PersonEntity>
@Environment(\.managedObjectContext) var moc

var body: some View {


VStack {
List(people) { person in
Text(person.name ?? "")
}
You now have access to
Button("Add Person") {
let person = PersonEntity(context: moc) the managed object
person.name = ["Mark", "Lem", "Chase"].randomElement() context of your
try? moc.save() persistent store.
}
} This is your place to
.font(.title)
} add new data, make
} data changes, delete
💡 data, and then decide if
you want to save it or
When a new data object (PersonEntity) undo it.
is created, you pass in the managed
The save function returns a object context it is associated with. Note: I named the
bool that indicates success That way, when you call the save property “moc” for
or failure. The question mark function on the managed object managed object
after try means the bool context, it knows which persistent context. Some also use
could be nil or have a value. store to write it to. “context”. It’s up to you.

www.bigmountainstudio.com 56 Core Data Mastery in SwiftUI


First Example

Questions & Answers

The @FetchRequest didn’t have to somehow What happens to the data after I quit the
connect to the managed object context that app?
we added to the environment? When the new data objects were created we
The @FetchRequest is so smart that it called the managed object context’s save()
automatically looks for the managed object function. This persisted the object to the store.
context in the environment. So if you quit the app the data is preserved.
If you re-open the app, the data is loaded from
If it doesn’t find one, you will see a purple the persisted store again and displayed on the
memory warning in Xcode that says: screen.
“Context in environment is not connected to a
persistent store coordinator”
How do I delete this data?
Use width: 214 This is when you know you forgot to set the
This book will show you how to do that but for
managed object context.
now, you can delete your app from the simulator.
That will remove the data from the persisted
storage that was connected to the app.

How did the view update automatically when


new people were created?
PersonEntity.name is optional. Can we make
All we did was call save() on the managed
it not optional?
object context. So how did the view update?
Unfortunately, no. The way Core Data works is
The @FetchRequest maintains a connection with
that attributes always come back optional.
the context. If data in the context changes, it
But you will learn nicer ways of handling this in
sends it to the @FetchRequest and the view is
the Displaying Data chapter rather than nil
updated. Pretty cool, right?
coalescing (??) values everywhere.

www.bigmountainstudio.com 57 Core Data Mastery in SwiftUI


First Example

4 Steps Done!
You have now successfully added data to your persistent store and have data successfully being fetched and shown on the view.

1. Data Model 2. NSPersistentContainer 3. NSManagedObjectContext 4. The View

Save Data Fetch Data

Stores Data

Provides a place to
Reads Model
change data
Create Data

www.bigmountainstudio.com 58 Core Data Mastery in SwiftUI


First Example

Summary
When looking at the total amount of code we had to create to get Core Data working, there really wasn’t all that much between the 3 files.

1
class FirstExampleContainer {
let persistentContainer: NSPersistentContainer
First, we created a class to
init() {
persistentContainer = NSPersistentContainer(name: "FirstExample") create our persistent
persistentContainer.loadPersistentStores { _, _ in } container.
}
}

2
@main
struct SwiftUI_CoreDataApp: App { And then we added the
var body: some Scene { managed object context
WindowGroup {
FirstExampleView() (viewContext property) to
.environment(\.managedObjectContext, FirstExampleContainer().persistentContainer.viewContext) the environment’s
}
managedObjectContext.
}
}

www.bigmountainstudio.com 59 Core Data Mastery in SwiftUI


First Example

Summary

3
struct FirstExampleView: View {
@FetchRequest(sortDescriptors: []) private var people: FetchedResults<PersonEntity>
@Environment(\.managedObjectContext) var moc

var body: some View {


Finally, we have our view
VStack { that used a
List(people) { person in @FetchRequest to get
Text(person.name ?? "") the data.
}
We also had to add a
Button("Add Person") {
reference to the
let person = PersonEntity(context: moc)
person.name = ["Mark", "Lem", "Chase"].randomElement() managedObjectContext
try? moc.save() in the environment so we
} could add data.
}
.font(.title)
}
}

The Core Data Concepts and First Example chapters were meant to help you understand the main parts of Core Data and to see how easy it
can be to get started. This is your foundation to build on.

www.bigmountainstudio.com 60 Core Data Mastery in SwiftUI


MOCK DATA

Many times you want to see a preview of the UI you are building WITH mock data. But how can you add mock data to Core Data without it
persisting? What if you want to test deleting data? You don’t want to keep having to add the same data over and over again.

In this chapter, I’ll show you how to set up mock data so you can see it in your SwiftUI Preview.
Mock Data

Data Model
For this chapter, we are going to use a simple data model with one entity and two fields. It is in a file called FriendsDataModel.xcdatamodeld.

FriendsDataModel
💡
As a convention from this
point on I will be adding
“DataModel” to all of my data
model file names.

I also add “Entity” to all entity


names so when used elsewhere, it
is easy to tell it comes from the
data model.
And here is the persistent container class we will start with. This is just like your first example:

class FriendsContainer {
let persistentContainer: NSPersistentContainer

init() { Remember, the name


persistentContainer = NSPersistentContainer(name: “FriendsDataModel") has to match the file
persistentContainer.loadPersistentStores { _, _ in } name of the data model.
}
}

www.bigmountainstudio.com 62 Core Data Mastery in SwiftUI


Mock Data

Persistent Store Location


Your persistent store for your app has a path, a URL, to its location. Let’s see where it is.
The persistent store descriptions are an array of
Let’s add a new line to our FriendsContainer to see this URL. persistent store objects that have properties to
allow you to further define certain aspects of a
class FriendsContainer {
persistent store, such as its URL (location) to
let persistentContainer: NSPersistentContainer
where it is stored on the device.

init() {
persistentContainer = NSPersistentContainer(name: “FriendsDataModel")
As you can see the persistent store is a
sqlite file with the exact same name as
print(persistentContainer.persistentStoreDescriptions.first!.url!.absoluteString) the name of our data model
“FriendsDataModel”.

persistentContainer.loadPersistentStores { _, _ in } We’re going to change this URL to a


} location that allows us to
} temporarily store mock data.

Optional("file:///Users/mark/Library/Developer/CoreSimulator/Devices/FDCCB8F9-79E4-499C-8CFD-2E8243B84B08/data/
Containers/Data/Application/490E0318-F97F-4BD5-907B-708B2C0D0ADE/Library/Application%20Support/
FriendsDataModel.sqlite")

www.bigmountainstudio.com 63 Core Data Mastery in SwiftUI


Mock Data

Mock Data Location


Apple gives us a special temporary location for our persistent store where we can load mock data, change, delete, etc. The data only last until the

preview redraws or your app stops running in the Simulator.

You want to be able to toggle this temporary path for mock data because your real app will not use this path.

Here is how you set the


class FriendsContainer { container’s location to a
let persistentContainer: NSPersistentContainer temporary location where
you can insert, change
and delete data and none
init(forPreview: Bool = false) {
of it will persist.
persistentContainer = NSPersistentContainer(name: "FriendsDataModel")

This means every time


if forPreview { you run the app with
persistentContainer.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") forPreview set to true, it
} will always start over.

persistentContainer.loadPersistentStores { _, _ in }
}
}

What about inserting mock data though?

Let’s do this next…

www.bigmountainstudio.com 64 Core Data Mastery in SwiftUI


Mock Data

Mock Data
class FriendsContainer {
let persistentContainer: NSPersistentContainer

init(forPreview: Bool = false) {


persistentContainer = NSPersistentContainer(name: "FriendsDataModel")

if forPreview {
persistentContainer.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}

persistentContainer.loadPersistentStores { _, _ in }

if forPreview { If forPreview is true then we want


addMockData(moc: persistentContainer.viewContext) to load up some mock data
}
}
}

extension FriendsContainer {
func addMockData(moc: NSManagedObjectContext) {
let friend1 = FriendEntity(context: moc)
friend1.firstName = "Chris"
The newly created managed
friend1.lastName = "Bloom" object context is passed in
because you need this whenever
let friend2 = FriendEntity(context: moc)
friend2.firstName = "Jaqueline" you create a new entity, such as
friend2.lastName = "Cruz" the FriendEntity.
let friend3 = FriendEntity(context: moc) OK, you have a temporary
friend3.firstName = "Rodrigo" Newly created entities are first location to play in and some
friend3.lastName = "Jones" added to context (memory) and mock data loaded up.
// ... then are saved and persisted on
the disk. Now let’s set up the SwiftUI
try? moc.save()
} preview!
}

www.bigmountainstudio.com 65 Core Data Mastery in SwiftUI


Mock Data

SwiftUI Previewing Mock Data


struct PreviewingData_Intro: View {

@FetchRequest(sortDescriptors: []) var friends: FetchedResults<FriendEntity>

var body: some View {


This is all you have to add!
List(friends) { friend in

Text(friend.firstName ?? "") Notice we’re not adding any


} data here.
.font(.title)
All you have to do is set
} forPreview to true and data
} automatically gets added.
Use width: 214 Nothing gets persisted.

struct PreviewingData_Intro_Previews: PreviewProvider {

static var previews: some View {

PreviewingData_Intro()

.environment(\.managedObjectContext,

FriendsContainer(forPreview: true).persistentContainer.viewContext)

This line is kind of long. Could it be shorter?

www.bigmountainstudio.com 66 Core Data Mastery in SwiftUI


Mock Data

Static Preview Property


class FriendsContainer {
static var preview: NSManagedObjectContext { You could create a
get { static property to
let persistentContainer = NSPersistentContainer(name: "FriendsDataModel") instantiate your
persistentContainer.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") persistent store, load up
persistentContainer.loadPersistentStores { _, _ in } some mock data and
addMockData(moc: persistentContainer.viewContext) then return your
return persistentContainer.viewContext managed object context
} like this.
} Because this preview property
is static, you will have to make
let persistentContainer: NSPersistentContainer the addMockData function
static too.
init(forPreview: Bool = false) {
💡
persistentContainer = NSPersistentContainer(name: "FriendsDataModel")
There are probably
if forPreview { thousands of ways you
persistentContainer.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null") can create your
} container for your
production app and for
persistentContainer.loadPersistentStores { _, _ in } previewing with mock
data.
if forPreview { I wanted to give you
FriendsContainer.addMockData(moc: persistentContainer.viewContext) Make the addMockData some ideas and options
} function static and refer to here so you could try
} it through the class now. different things and see
} what works for you!

www.bigmountainstudio.com 67 Core Data Mastery in SwiftUI


Mock Data

Shorter Property for Preview


struct PreviewingData_Intro: View {

@FetchRequest(sortDescriptors: []) var friends: FetchedResults<FriendEntity>

var body: some View {

List(friends) { friend in

Text(friend.firstName ?? "")

.font(.title)

} Then in your preview, you


}
simply refer to this static
property.
Use width: 214

struct PreviewingData_Intro_Previews: PreviewProvider {

static var previews: some View {

PreviewingData_Intro()

.environment(\.managedObjectContext, FriendsContainer.preview)

www.bigmountainstudio.com 68 Core Data Mastery in SwiftUI


DISPLAYING DATA

In your data model, most of your entity attributes will be optional types. You don’t have a choice in this matter.

This means when you want to display data, there’s a lot of optional handling because if a value is nil, you have to provide a default value.

You are going to learn how to make this easier.


Displaying Data

Data Model
For this chapter we are going to use this data model. It is in a file called BooksDataModel.xcdatamodeld.

BooksDataModel

I wanted to have a data model that used a lot of


different data types.

Core Data will make a lot of these types optional.

The ones with the red dot will become optional


in Swift.

Can I just uncheck Optional in the Data Model Inspector?


No. This does not control whether the attribute type gets converted into a Swift optional
type or not.
It determines if an error is thrown when inserting or updating if that value is missing.

www.bigmountainstudio.com 70 Core Data Mastery in SwiftUI


Displaying Data

Handling Nils
struct DisplayData_Intro: View {
@FetchRequest(sortDescriptors: []) private var books: FetchedResults<BookEntity>

var body: some View {


List(books) { book in There’s a lot of work on the view to
VStack(alignment: .leading, spacing: 12) { handle all of these nils.
getImage(imageData: book.cover)
.resizable()
.scaledToFit() Notice Core Data won’t make booleans
HStack { and numbers optional.
Text(book.title ?? "")
.font(.title2)
Spacer()
Image(systemName: book.available ? "checkmark" : "xmark")
}
Text(book.lastUpdated?.formatted(date: .numeric, time: .omitted) ?? "N/A")
Text("Pages: \(book.pages )")
Text((book.price ?? 0) as Decimal, format: .currency(code: "USD"))
Use width: 214 Link(destination: book.url ?? URL(string: "https://www.bigmountainstudio.com")!) {
Text("Learn More")
}
Text(book.bookId?.uuidString ?? "")
.font(.caption2)
}
.padding(.vertical)
}
There’s also a lot of work to
}
not only handle if an image
func getImage(imageData: Data?) -> Image { is nil but to convert it into a
if let data = imageData, let image = UIImage(data: data) {
return Image(uiImage: image) format SwiftUI can use.
} else {
return Image(systemName: "photo.fill") Let’s simplify this.
}
}
}

www.bigmountainstudio.com 71 Core Data Mastery in SwiftUI


Displaying Data

Extending the Entity Class


// Handle nils and formatting
extension BookEntity { All the entities defined in the Data Model
The goal here is to get var viewCover: UIImage { file get converted into classes.
the data “display ready”. if let data = cover, let image = UIImage(data: data) {
return image
} else { Xcode “synthesizes” or autogenerates the
Here are some return UIImage(systemName: "note.text")! // SF Symbol
}
entity and attribute information into Swift
examples of handling
} classes and properties.
nils, images, and
formatting. var viewTitle: String {
title ?? "No Book Title" You can then extend or add on to those
} autogenerated classes to add your own
I prefix all of my var viewAvailability: String {
properties and functions.
properties with “view”. available ? "checkmark" : "xmark"
}
var viewLastUpdated: String {
That way when I use return "Last Updated: " +
autocomplete, I can just (lastUpdated?.formatted(date: .numeric, time: .omitted) ?? "N/A") // Stands for "Not Available"
}
start typing “view” to var viewPages: String {
see all of my properties. "Pages: \(pages)"
}
var viewPrice: String {
Bookmark this page so
that when it comes time
let formatter = NumberFormatter()
formatter.locale = Locale.current 💡
formatter.numberStyle = .currency
for you to format your return formatter.string(from: price ?? 0)!
values you can come } Note: You never want to edit the
here to find examples var viewUrl: URL { autogenerated code or else you will most
url ?? URL(string: "https://www.bigmountainstudio.com")!
for most data types. } likely lose your changes if the entity gets
var viewBookId: String { regenerated again.
bookId?.uuidString ?? ""
}
} Create an extension instead.

www.bigmountainstudio.com 72 Core Data Mastery in SwiftUI


Displaying Data

SwiftUI View with Extended Properties


struct DisplayData_HandlingNils: View {
@FetchRequest(sortDescriptors: []) private var books: FetchedResults<BookEntity>

var body: some View {


Look how much cleaner this all
List(books) { book in
VStack(alignment: .leading, spacing: 12) {
looks compared to the version
Image(uiImage: book.viewCover) we started with.
.resizable()
.scaledToFit() All of the formatting logic has
HStack { been extracted into the entity
Text(book.viewTitle) extension class.
.font(.title2)
Spacer()
Image(systemName: book.viewAvailability)
Use width: 214 }
Text(book.viewLastUpdated)
Text(book.viewPages)
Text(book.viewPrice)
Link(destination: book.viewUrl) {
Text("Learn More")
}
Text(book.viewBookId)
.font(.caption2)
}
.padding(.vertical)
}
}
}

www.bigmountainstudio.com 73 Core Data Mastery in SwiftUI


Displaying Data

Process & File Organization

File Organization I keep my data model, container, and entity extensions all in the same folder.

If you are using the companion Xcode project, you will find all the data
models and related files in the Data Models folder and within their own
folders from there.

Remember:
• Data Model - Tells Core Data what the data will look like.
• Container - Creates your persistent container and gives you a managed
object context.
• Entity Extensions - Extends the autogenerated entity classes with your
own properties to format the values and handle nils for use on your UI.

Xcode Project Navigator


In your own app, you will most likely only have ONE data model, container,
and as many entity extensions as entities in your data model.

www.bigmountainstudio.com 74 Core Data Mastery in SwiftUI


WHERE TO GO FROM HERE

Thank you for reading the Core Data Quick Start in SwiftUI book. • How do you use concurrency in Core Data?
• What can I do to allow users to undo and redo Core Data
This is just the BEGINNING of a larger book called Core Data changes?
Mastery in SwiftUI. In the Mastery book you will learn much more • Can I split out my data model into multiple entities and connect
about Core Data and be able to answer questions such as: them with relationships?
• How do I create fetch requests that can filter and sort my data? • How do I use Core Data with observable objects and SwiftUI
• Can I fetch data that can be bound to a List with sections? views?
• Is there a way to add data validation to my data model and show • Can I version my data model with changes for new versions of my
the results in my SwiftUI views? app?
• How do I use the managed object context to insert, update, • How can I use Core Data and sync with iCloud between devices?
delete or check for changes before saving?
THE END

76

You might also like