In the last lesson, we managed to use the Codable protocol to save our to-do list items into plist 1
and we were able to retrieve it and add new items as we pleased. 2
The next step is embark on a new journey and a new way of persisting our data. For this lesson and a 3
lot of the coming lessons, we're going to be diving into Core Data. And I'm going to walk you through 4
how we can perform all of the CRUD operations using Core Data. 5
But first, we need to learn how to set up and configure our Core Data DataModel in order to use it in 6
our projects. 7
Now, the first thing if you remember is that when we choose a template to create a new project, there's 8
this checkbox here that says Use Core Data. 9
Now, for our current project, I asked you not to check it because we were going to be looking into various 10
different methods of persisting our data before we come to this module. 11
So if we have a look, let's just create a CoreDataTest app and I'm going to check use Core Data, 12
and we're going to hit Next, 13
and I'm going to save it onto my desktop. 14
And don't worry about creating a git repository. 15
We're just gonna have a look at this test project to see what automatically gets created by Xcode 16
when you check that tick box. Now, the first thing that you notice that's different from your normal template 17
is that you get this Core Data DataM odel. And inside here is where we set up all of our data and structure 18
it for use with Core Data. 19
The other thing that Xcode adds is inside the AppDelegate, it adds a whole bunch of helper code which 20
you're going to need every single time you use CoreData. 21
So they've just given it to you for free when you tick that checkbox. 22
So what are we going to do in our project? 23
Are we gonna have to rewrite it from scratch and tick that checkbox? 24
I mean there's a lot of cases when you make an app when you--and you don't know that you need to persist 25
your data using Core Data, 26
maybe, you know, initially, you thought, "Oh, it's gonna be a really small amount of data, 27
I'm just going to persist it using plist." 28
But then at some point, you realize that it's actually become this behemoth and you now need some sort 29
of formal DataModel manager. 30
So that's why we created this project Todoey without checking that use Core Data checkbox, so that 31
I can show you how you can add Core Data to any project even at a later date. 32
So the first thing that we're going to do is we're going to add that Core Data model. 33
We're going to go to File, New, File. And we've normally been playing around with this section which is 34
the source, but now, I want you to scroll down to the section that's called Core Data and we're going 35
to create a new Data Model, and hit Next. 36
Now, we're going to call this Data Model, DataModel. 37
I know it's not very imaginative, but it makes sense to most people. 38
And I'm going to drag it out of controllers and put it inside DataModel where it fits in much better. 39
Now, if we go back to that CoreDataTest app where we checked using Core Data, we can actually just simply 40
copy and paste all of this code up to and including applicationWillTerminate, and we can paste it into 41
our project. 42
So I'm going to delete applicationWillTerminate and I'm going to paste what we copied over instead. 43
Now, EXCO is going to complain because it doesn't know what persistent containers are unless we, of course, 44
import the CoreData framework. 45
And one thing we have to check to make sure is that the name here where it says the persistent container 46
name has to match with the name of our DataModel. 47
And if you remember, we called ours DataModel with a capital "D" and the capital ",." 48
so we have to make sure that when we copy this code over, that we have to change this to match our 49
"DataModel" name. 50
So, now at this point, our project for Todoey is exactly the same as if we checked that box to include 51
Core Data. So we can now close down this CoreDataTest project and we can delete it because we're not 52
going to need it anymore. 53
We've already gotten all the code that we got given from Xcode and we've incorporated it into our current 54
project. 55
Now, let's head over to our DataModel and we're going to create a new entity. 56
So you'll notice that when you start working with Core Data, it's almost like we're in a different world. 57
They use different words for things that we already have a good grasp of. 58
So, for example, entities are pretty much equivalent to classes, and each entity has a whole bunch of attributes, 59
and those attributes are almost like our properties that we've gotten used to. 60
But you can also consider that each entity is basically like a table of data. 61
So for every single Excel sheet that you have, you might have a single entity inside your Dore Data data 62
model. 63
So let's get started and we'll explain as we go along. 64
So we're gonna go over here and we're going to click on Add Entity which gives us this brand-new entity 65
and we're going to rename it to something that makes sense, rather than just Entity, right? 66
So you can do that either by clicking here or you can also just edit it in the attribute pane. 67
So, now inside our right-hand pane, you can see that we've got this new icon that looks to me a little 68
bit like a welding mask. 69
I don't know why it represents Core Data, but it just does. 70
So this is the pane under which we're going to edit all of our properties related to our entities and 71
our attributes. 72
And it's also here that we can change the name of our entity and we're going to call ours Item because 73
that's what this class or entity is going to represent. 74
It's going to represent individual items just as we did here using our class. 75
And if you look at our class, you can see that it has two properties which we now know are called attributes 76
in Core Data. 77
So we need to add these two attributes to our item entity and we do that by clicking this plus arrow 78
here. 79
So the first attribute, we're going to call title and the type of it is going to be String. In the attribute 80
pane, 81
there's this checkbox called Optional. And we want to make sure that each and every item must have a 82
title because, I mean, otherwise, what are you saving, right? 83
If an item doesn't even have a title. 84
Now, so we have to uncheck that box where it says Optional and make this a required attribute. 85
Now, there's other attributes to these entities that might be optional, 86
for example, like a due date for each item. But the title is not, 87
so let's go ahead and add that. 88
Now, the next thing that we're going to add is the done attribute and this is going to be a Boolean, 89
so we can select like that down here, and we're going to make this attribute nonoptional as well. 90
So, now you can see that we've essentially replaced our Item class with our item entity and all of its 91
attributes. 92
So we can now safely delete our Item class and move it to Trash because we've essentially replaced what 93
it does using Core Data. 94
Now, there's one last thing that we need to do inside our DataModel inspector and that is to change 95
the module from global namespace to Current Product Module. 96
Now, this is something that probably won't break our project at this stage, but it's something to be aware 97
of 98
once your Core Data project gets more and more complicated, especially if your app requires multi-threading, 99
you might end up with weird errors if you don't select this as Current Product Module. 100
Now, the other thing that you'll notice here is that there is this property called Codegen. 101
And if you click on it, there's three options. 102
Now, let's go through what each does. 103
So the current and the default selection is called Class Definition, and what this does is that it converts 104
your data, your entities, and your attributes into classes and properties, so you can use them and manipulate 105
them just as you would if you had created a class with these properties. 106
Now, the slimy mysterious thing is that when Xcode automatically generates these classes, it doesn't 107
show up in our project navigator, so we can't actually view it unless we're really determined. 108
So if you are really determined to find it and have a look at it, then you can follow along with me. 109
Alternatively, you can just watch me show you where it is and trust that your code file is also automatically 110
being generated as long as you've got that Class Definition checked. 111
Now, in order to locate those files, all we have to do is head into Finder and we're going to navigate 112
right into the root. 113
So if you have difficulty finding your Macintosh hard drive, then all you have to do is just on any given 114
folder, hit command and hit the up arrow, and this will take you all the way up until you can no longer 115
go up any further,and you should be at your Macintosh HD which is your root. From here, 116
you're going to go into the Users folder, and then you're going to find your current logged in user 117
username, and then we're going to go into Library. 118
Now, if you don't see a library inside your Users folder, then all you have to do is just open up Terminal 119
and type chflags nohidden ~/Library/ and hit enter and that will make your library folder 120
unhidden inside Finder. And inside Library, we're going to go to Developer, and then Xcode, 121
and DerivedData, and then in this folder, we're going to find our Todoey app. 122
So it should be called Todoey with a whole bunch of jumbled letters afterwards. 123
And here, we're going to look for a folder called Build. and inside Build, we're going to go into Intermediates, 124
and then Todoey.build, and then Debug, Todoey.build, and then we're going to go to DerivedSources. 125
And finally, CoreDataGenerated, and DataModel. 126
So it's a long path to chase down but, eventually, you get here. 127
And what do we find? We find three Swift files which is the name of your entity and Properties, and your 128
Item, and your Core Data class. 129
So if we double click on it, it should open inside Xcode, and we can have a look at what they look like. 130
So the two most important files that Xcode generates for you is your Item class and your Item properties. 131
So the Item class file gets generated once and it doesn't get modified unless you've deleted the entity 132
or you add a new entity.Bbut this file, the Core Data properties for your items, 133
this has regenerated many times. 134
So if you try to write any code in here, it seems to get wiped and replaced with whatever xcode wants 135
to put in here. 136
So these are both not good places for you to put your own code. If you wanted to put in your own custom 137
initializers or custom functions for your Item class, then instead of using the default which is class 138
definition, you'll want to use Categories/Extension. And if you have this selected, then you need 139
to create your classes that are identically named to your entities, and Xcode will automatically link 140
them up to allow you to use CoreData. 141
Now, the other option here is Manual/None where there is, literally, no cogeneration at all, 142
there's no linkages behind the scenes, and you have to do all the work yourself. 143
And this is probably the one that's least used in practice. And the class definition is probably the 144
one that's least effort, quickest to set up, and easiest to understand. 145
But the one that's actually most used, that you'll see in the wild is actually the category extension 146
because sometimes developers might want to add in some custom code, and so you'll see that used pretty 147
often. 148
But I would say that a lot of people do use Class Definition as well, just because it's so easy to implement. 149
And that's the one that we're going to use. 150
So if we have a look back at the Swift file where Xcode automatically generated this class declaration 151
for our Item entity, then you'll see that our Item entity inherits or subclasses NSManagedObjects. 152
An NSManagedObjects are basically Core Data model object. 153
It's similar but not quite the same as our standard objects, but by subclassing NSmanagedObject, 154
it allows us to manage this class using CoreData. 155
So if you do create your own custom classes and you go for the option of Categories/Extension, 156
then you'll also want to inherit from NSManagedObjects in order for your code to work. 157
So, now that we've seen the automatic code that gets generated behind the scenes, let's take a look at 158
the code that we got inside our AppDelegate. 159
So if you remember, this was the code that we copied and pasted from a new project that has the use code 160
data checkmark checked, and what we get is a global variable called persistentContainer, and also a 161
method called saveContext. 162
So I'm just gonna get rid of all of this commenting that Apple has meticulously added, just so that our 163
code is a little bit shorter and we can see it all on one page. 164
I'm also going to delete the comments inside applicationWillTerminate and I'm also going to delete 165
all of these methods excluding didFinishLaunchingOptions. 166
So, now you should-- 167
So, now in your AppDelegate, you should have didFinishLaunchingWithOptions, as well as 168
applicationWillTerminate inside which you call self.saveContexts which is that method that Apple gave us 169
for free. 170
And we've also got this lazy variable code persistentContainer. 171
So the first question you might have is, "I've never seen this keyword before. 172
What does lazy do? 173
Well, you know how there's some people who if they need to get to work at 9:00, they'll wake up at 6:00. 174
You know, they'll spend half an hour doing yoga or some crazy stuff like that, and then do a whole bunch 175
of prep work, eat a proper breakfast. And those people are not lazy. But then there's another category 176
of people, myself included, which, you know, most people would categorize as lazy, and they're the sort of 177
person who if you need to be out the door by 8:30, you're probably wake up around 8:20, and try 178
to get everything done in 10 minutes, just so that you can have that extra hour of peaceful sleep. 179
So this is kind of similar to what lazy variables are. When we create a variable that we declare is lazy, 180
then it only gets loaded up with a value at the time point when it's needed, i.e., when you tried to use 181
this thing called persistentContainer that is when all of this code is going to run, and it's going to 182
have a value set. 183
So whereas the lazy person gets a lying benefit, the lazy variable gets a memory benefit. 184
So you're only occupying the memory when it's needed, rather than having everything set up beforehand. 185
So inside this lazy variable, we're creating a NSPersistentContainer 186
and this is basically where we are going to store all of our data. 187
And even though it's called an NSPersistentContainer, which sounds kind of fancy, it's actually going 188
to be a SQLite database. 189
So for those you guys who have worked with databases, SQL, SQLite, then this is basically what 190
the NSPersistentContainer is. 191
Now, the reason why it's called persistentContainer, and not just your SQLite database, is because 192
you can use different types of persistent containers. 193
So for example, you can use XML, instead of SQLite, but that's a whole other topic. 194
Just remember that your default persistent container is going to be a SQLite database. 195
Now, we create a constant called container that sets up this new persistent container with the name of 196
our DataModel, 197
and these two have to match so that all the behind-the-scenes setup and the relationships gets created 198
properly. And then we're going to load up this PersistentStore and we're going to log if there were 199
any errors. But if there weren't any errors, then we're going to return the container that we loaded up 200
and we're going to set it as the value of this lazy variable called persistentContainer. And we'll be 201
have to access it inside other classes in order to persist and save our data into our SQLite database. 202
Now, there's this other helper method called saveContext and this just provide some support to saving 203
our data when our application gets terminated. 204
But here, you see this thing called a context and we're going to look into the context a lot more later 205
on. 206
But essentially, the context is an area where you can change and update your data, so you can undo and 207
redo until you're happy with your data, and then you can save the data that's in your contacts or your 208
temporary area to the container which is for permanent storage. 209
So if you remember our lessons on Git and gGitHub, the context is similar to that staging area, that temporary 210
area where we can change things and update the things that we want to commit, and then only once we're 211
ready, do we actually commit the data to source control. 212
And in this case, it's exactly the same. 213
So the two things that you need to understand from this code is that we create a new 214
NSPersistentContainer using our CoreData DataModel. And this persistentContainer is the database that we're going 215
to be saving to 216
and as a SQLITE database. The second thing is that we have this thing called a context which is 217
what's called a scratch pad or a temporary area where you can update, change, delete your data until you're 218
happy with the format. 219
And then we basically commit it to permanent storage. 220
So these concepts are core to understanding Core Data and how it works. 221
So we're going to be revisiting it quite a few times. 222
So if you don't get it right now, don't worry, because I'm gonna be repeating the concepts here a few more 223
times until we get it. 224
So, now that we've seen how we can configure and set up Core Data to be used inside our Todoey project, 225
in the next lesson, we're going to look at the first letter of CRUD which is how do we create or how 226
do we save our data using Core Data. 227
So for all of that and more, see you on the next lesson.