iOS Core Data QuickStart Tutorial 2020

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello kokuru welcome to the core data series in this lesson we're going to go through what core data is its benefits and how you're going to use it with xcode first of all what is it core data is apple's local object graph persistence framework now before i scare you away in simple terms it's a way for you to store data on your device locally and then retrieve it later for use the data stays locally on the device so it's not a solution for sharing data with other users and it's not a solution for syncing data across multiple devices although some of that can be done when you combine core data with cloud kit next why should we even use core data well assuming you need to store data in your app some benefits of using core data include number one it's a first party apple framework so it plays nicely and has a tighter integration with other apple apis and frameworks number two being a first party framework means that apple is going to make sure that any new technology it releases will work with it at least i'd like to think that apple would make a bigger effort to make sure that core data plays nicely with anything that they release number three you don't have to install any third-party sdks which means you don't have to work with cocoapods or trying to keep third-party code libraries up to date all right now for some drawbacks of using core data number one it's not a remote database solution although syncing across devices should be able to be done with cloudkit to be honest i haven't looked into this very much myself yet number two the classes and methods to work with core data may be confusing at first so there's a little bit of a learning curve but i hope in this video series i can simplify that for you number three you have to retrain your brain to think of core data as an object graph persistence framework object graph persistence framework let's take a look at what that means it all has to do with how you interact with core data you see with traditional databases you explicitly insert create update and delete data from the database now even though under the hood core data is using an sqlite database you don't have to explicitly tell core data to insert create update or delete you just create and work with objects in your app like normal and behind the scenes core data will manage the data persistence for you let's take a look at a diagram to see how this works okay so let's say you have two classes family and person the person class contains some properties and the family class has a property storing the person objects for that family you create a family object in several person objects and then you relate those person objects to the family object now you want to store it in core data how do you do that well there are a few core data components that are needed one is the persistent container you can think of this as a representation of the core data store or database however your objects don't interact with the persistent container directly there's a layer on top of the persistent container called the managed object context think of this as sort of a data manager layer your objects will go through the managed object context to be stored or retrieved from the persistent store now these objects in memory along with how they relate to each other is called an object graph when you store the objects into core data all of the data in the properties along with the relationships are preserved in other words the object graph when you retrieve them from core data back into memory you can get them back in the same state they were in before so that's why they call core data an object graph persistence framework now to complete our understanding of how core data works let's revisit our diagram in previous lessons i've shown you how to work with json and decode them into usable objects in our app this process of changing the data into a different format and back is known as encoding and decoding or serializing and deserializing while core data needs to do the same thing here it serializes the object into a format that can be stored in the underlying sqlite database and then it'll deserialize it back into the objects in memory the code or functionality to do that serializing and deserializing process is with a class called ns managed object so if you want your class to be able to be captured in core data you need to subclass ns managed object that gives objects of your custom class the ability to be stored with core data okay so now your objects can be serialized and stored with core data however when you want to bring that object back from core data how does it know what format to deserialize that data back into in other words if you're trying to bring your person back how does it know about your person class and what properties your person class contains well here's the final piece of the core data puzzle in this example we use the person class that subclasses ns managed object well you don't actually create and write this person class yourself instead there's a visual editor where you have to define the class in the core data model they call the class an entity and the properties of your class are called attributes of that entity then after you've defined the entity and attributes in other words your class and its properties you generate the swift classes from this core data model file it's just a command you run from an xcode menu and they'll generate the class files for what you've defined in the core data model the generated class will automatically be a subclass of ns managed object so that core data can serialize and deserialize it then you use that generated class like you would any other class and core data can now store objects of that class and bring them back when needed so let's do a quick recap of how we're going to work with core data you define your entities and attributes in the core data model then you generate your classes from the core data model then you get a reference to the core data persistent container from the persistent container you get a managed object context and through that managed object context you can create objects and store them in core data for retrieval for later use now core data has a stigma of being hard to understand and use i hope i've demystified it at least a little bit for you in this video in the next lesson we'll do a real example of using core data in xcode all right i'll see you there hey code crew in this lesson we're going to do a real example of using core data inside xcode i'll go through two different scenarios number one how to start your xcode project with core data enabled and number two how to add core data functionality to an existing xcode project now even if you're only interested in number two i would still highly recommend that you watch through part one because in part one i'm going to be highlighting the different core data components that are needed now just a quick recap of the previous lesson in case you didn't see it to work with core data we need four things number one is to define our entities and attributes in the core data model number two is to generate the classes from the core data model number three get a reference to the core data persistent container and then number four get the managed object context through which we save and retrieve our objects all right let's jump into xcode and do this all right first we're going to talk about setting up core data with a brand new xcode project and then afterwards we're going to talk about how to add core data to an existing xcode project so here i'm going to set up a brand new xcode project here and i'm going to choose single view application and all you need to do to set up core data is to make sure this check box is enabled so let's call this our core data demo and just make sure that's enabled and let's hit next oh by the way i am still using storyboards ui kit here so if you're following this demo you can select the same thing let's click next and i'm going to save this on my desktop now the first thing you'll notice is that enabling that use core data option gave you this file along with your new project this data model file and when you click that you get this visual editor to define your entities and attributes if you remember from the slide we just saw the first step is to define our entities and attributes so let's go ahead and do that through this visual interface down here click add entity and you're going to see your new entity here now you can either edit the name by clicking it once so you make it editable or you can come in here and just change the name of the entity so i'm going to use the same example as we did in lesson one of this core data series which is to use the person and family analogy we're only going to start with person for now later when we talk about relationships in core data then we're going to define our family entity as well all right so before we move on to attributes there are a couple of things i want to point out in terms of the attributes for the entity number one is the name which we've just defined number two is this this module or namespace if you have an xcode project which houses multiple modules or xcode or other projects i mean then you can define which namespace you want this entity to be a part of by default it's global so for i think for most of us who are just creating an xcode project for a single app that has one module you don't have to worry about this but just in case your project has multiple modules and you don't want this person class name to clash with some other person class name in another module then you can definitely define uh the namespace here or rather which namespace this person is part of the next part is codegen now after we define our entities and attributes when we generate the classes you can actually do that either manually or have xcode do that for you when you build and run the app by default xcode will do it for you automatically but for now i want you to change this option to manual none because i want to show you how to do it manually and then i will also tell you about the other two options because there are trade-offs to be made so let's go ahead and select manual none for now all right now we're ready to add our attributes so under here you can click this plus symbol to add a new attribute or you can click this add attribute icon down here which i think is not as intuitive as this guy so go ahead and click add item and then you can give it a name so our first one was just name so let's just name it that and then the type let's choose string so we're going to add another one we had gender here and again this was a string now the next one was age and the type was actually an int now you'll see in the type here there's integer 16 32 and 64. if you're not familiar with what those are basically they define the size of the integer now i'm going to pull up a web page here that shows you the differences with the different integer types so you'll notice that there's different types of ins there's 8 32 64 and you can see that the ranges go up as this number goes up and there's also a u-int version of each of these sizes u stands for unsigned which means that there's no negative range so as you can see in 64 gives you the largest range but we don't usually have to select which type of in we use right when you define in swift of a new variable of the int type you don't have to specify any of these well under the hood that int type that you specified is one of these types and it really depends on what platform your code is running on because different cpu architectures store data differently some are 32-bit some are 64-bit and some as you can see might be 8 or 16. there's this website here that i found specifying the different architectures of the ios platforms and you can see in here sort of what cpu architecture it's using and whether it's 32-bit or not and as you can see as we scroll down this list these are the older iphones and ipods and ipads and as you scroll down to the newer ones at this point you know in 2015 it looks like everything starts to be 64-bit so as you can see here down to you know the latest ones down here it's all 64-bit so it's safe to say when you're declaring a swift int and your app is going to be running on one of the newer devices 2015 and above that it's going to be 64-bit architecture so your int is actually an int 64 with this range so going back to the core data now what should you specify here well don't get the wrong idea just because for the age you won't need such a big range thinking specifying in 16 might save you some memory or save you some space it doesn't work like that the memory allocated for that age variable will still be 64-bit so you might as well just choose 64-bit so that's kind of a long explanation about those about what those differences are now you might also notice on this list that we don't have array types or you know object types or anything like that well if you wanted to specify let's say an array of let's say for name for example and we wanted to specify an array of names instead you choose transformable and then over here on the right hand side for the name attribute you can set a custom class and we can set this to be a type of string array or if it's maybe referencing another custom class that you have you can put the class name there and when this entity gets generated this uh name attribute will be transformed into a name property of that type so i'm just going to set it back to string for now so if you want to learn more about configuring entities there is apple documentation for that talking about the different attributes and the different things you can specify i'll link this page in the description below the video now i want to talk about generating code from this entity generating the classes i mean now earlier i mentioned that there are a couple ways to do it manual class definition and category extension let's start by manually generating this so go ahead to editor click create ns manage object subclass make sure that there's a check mark beside your data model and a check mark beside your entity click next and you can just save it anywhere it's going to create two files here and typically what i'll do is create a model group and move that in there so things are a little more organized so you'll notice that there are two files for your one entity and it's person plus core data class and person plus core data properties let's start with this one now this one is the class declaration for person or your entity you know and it's subclassing ns managed object which i told you before that your entity or your class needs to do in order to be saved and retrieved and basically work with core data now the second file is an extension of your class so if that's new to you just think of these two files combined together is your complete person class this extension contains all of your attributes as properties and you can see the data types are exactly what we specified notice that there's also this type method here called fetch request so later on we're going to be able to generate a query or a fetch request simply by typing person the class name dot fetch request but we'll get into that part later for now the key thing i want to mention is why this is split into two classes um the reason is because for this class definition or declaration here this is where you want to put all of your custom code if there are custom methods you want to put into this class this is where you would do it this one i would try not to modify because when you regenerate these classes maybe you've made a change to your model and you regenerate these classes whatever changes you've done here are going to be overwritten so speaking of which whenever you make a change to any of the attribute names or the types or maybe you add a new attribute or something like that you're going to want to regenerate those classes so then you can go ahead and delete your classes if you've if you've made changes here definitely don't delete this file only to only delete this one right here right because this is the one that just defines all of your properties but this is what manually generating your classes and tails you're going to have to manually make sure that this extension this property extension here is up to date with what you've defined here now let's talk about having xcode automatically generate these classes for you so if we click on the entity and we go under code gen by default if you remember earlier by default it was set to class definition when it's set to this you don't have to manually generate the classes so you wouldn't have these these would you would basically delete these you wouldn't have you wouldn't have done this what happens instead is that when you build your xcode project those two files right there they automatically get generated for you behind the scenes you'll never see them that means you cannot edit them so a drawback with having xcode automatically do this for you is that if you wanted to put some like custom logic or custom methods in your person class you can't because you won't have these two files to modify um but the advantage is that you don't have to manually make sure that these this file is up to date with whatever you've defined here because every time you build your xcode project those two classes will get regenerated behind the scenes so what we've done here is we've manually generated these and i have the entity set to automatically generated on build what's going to happen if i build the project now well i'm going to get an error because what's happening is when i hit build on xcode it's trying to generate those two files for the entity because i've set it to that but it also recognizes that i have these two files here in my project so it's clashing if you look at the error it's going to say you know multiple commands produce that file so this is what you don't want in order to fix a problem like this you can simply go ahead and delete these move these to the trash if you want to ultimately have xhood automatically generate them to you for you i mean you move these two files to trash go to product and then clean build folder make sure you remove any artifacts and then you can rebuild your project or if you want if you want to manually do it just set this to manual none but you cannot have a combination of having xcode automatically generated for you and have these existing in your exclude project all right so now for the last code gen option which is category extension when you have it set to this xcode is only going to generate this extension file for you automatically which means you can go ahead and delete this now this is sort of like a happy medium you can just straight up move it to the trash this is a happy medium because you still get this one file which you have to manually generate initially and then you go ahead and delete that category extension file but now you can add your custom logic in your custom methods and you don't have to make sure that the extension containing all of the properties is up to date with the model because having it set to a category extension for the code gen every time you build your xcode project it's going to generate that half of the class for you and right now i have an error probably because i didn't build my um build sorry clean my build folder as you can see it's still complaining multiple commands produce so i'm going to go back to product clean build folder and i know that having this code gen set to category extension and having this other half here if i press command b i'm going to get the full definition of my entity so i guess to sum it up manual is full control right you have to generate two files but you have to just make sure that it's like congruent with what you've defined here class definition is no control you don't get to add you don't get to modify the classes at all it gets generated behind the scenes when you build the xcode project and category extension is it automatically generates half of it for you and the other half you can customize the code okay so now we've defined our entities and attributes we've generated the classes now we need a reference to the core data persistent store well when you created this xcode project and you enabled use core data in the app delegate it's actually set up something additional for you down here you can see that now we have this persistent container property and this lazy keyword just means that it's not going to run all this code and create that container until you access it for the first time but this is your core data persistent container and it's a property in your app delegate so that's how you're going to access this persistent container as you can see here this name here maps to this core data this data model file right here all right so because this property is in the app delegate we can access it from any view controller or any other class in our entire project all right now let's go into the view controller and let me show you how to access the persistent container from there so we need a reference to the persistent container you can access the app delegate first by typing ui application i don't know about this one but this is how i would normally do it uiapplication.shared.delegate and you can see that it's optional here but the type is ui application delegate but we got to cast it as our app delegate okay and then now that it's our app delegate you can access the persistent container property right so this gives us access to that core data persistent container but if you remember from lesson one we don't interact with the core data persistent container directly we use the managed object context and in order to get a reference to that so that we can use the manage object context we just have to access a property on the persistent container called the view context you can see the data type for this is ns managed object context so this is actually what we need in order to store our data retrieve our data from core data and all of that but don't worry i'm getting a little ahead of myself because in the next lesson we're going to look at creating retrieving updating and deleting data through the managed object context for now i just wanted to show you how we can access the persistent container and also the managed object context now before we go into adding core data to an existing project i just want to show you one more thing in appdelegate because aside from this persistent container property there was also another thing down here called it also added this save context method and as you can see all this method is helping you do is it's getting a reference to the managed object context and then detecting if there has been any changes to the data and then saving right so it's just an easy way for you to save changes to your persistent container so you can do it by simply calling the save context method of the app delegate okay so when you start a new xcode project and you enable core data right off the bat you get the core data model file included and in the app delegate you have methods to access the core data persistent container and manage the object context now if you have an existing xcode project that you want to convert to using core data you won't have these things currently in your xcode project now let me show you how to add them so that you can use core data all right so now let's say you have an existing project that you didn't set up with core data so i'm just going to create a test project here and i'm going to i'm not going to enable use core data let's create that there and so let's say this is your existing project well all you have to do number one is add that data model file so go ahead and add a new file and under core data choose data model right and you can save this uh with whatever your name of your project is so i guess i'll call this testproject.xc data model and here you know you have your entities you're going to define your entities and attributes as normal also in appdelegate you'll notice that you do not have that persistent container property that i showed you and we don't have that save context method as well so you would just essentially add that code here but i don't really know that code by heart and i don't expect many people will so what i usually do is i create a brand new xcode project with core data enabled just to get that code and i'll copy and paste it in here so i can take that demo that we were just working on and i can copy this right that's the persistent container property but you have to make sure that this name right here matches that right so test project and that's the that's the core data data model file that you added and you also have to import core data at the top because otherwise the classes wouldn't be recognized right and then you can go back to your other project and just copy the saved context code over as well and it's as simple as that now the other thing is in an existing project you probably have your own model files already or your own model classes i mean you would have to redefine them as entities here along with their attributes and all of the relationships which a couple lessons later we'll talk about but you'd have to redefine all of those things and then regenerate the classes to replace your current model classes and then you would also have to alter the way that you get the data and in the next lesson you'll learn how to create retrieve update and delete data from core data so you're going to have to modify your existing project a little bit so that it uses that managed object context to fetch the data save the data and all of that stuff all right so in this lesson you learned how to set up your xcode project to use core data in the next lesson you'll learn how to create retrieve update and delete data from core data so i'll see you there hey code crew in this lesson we're going to continue our core data series and i'll show you how to create retrieve update and delete data from core data all right now let's jump into xcode all right so in this xcode project i'm going to show you how to create retrieve update and delete data from core data now i did set up a lot of the ui for this project and i'm only going to be focusing on the core data transactions bit and the reason for that is because if i showed you how to build the ui 90 of this lesson would have just been building ui with 10 being the actual core data bits which is the focus of this lesson so that's why i built it out but i'm going to walk you through the ui work that i've done so far and i'm going to show you where the missing core data bits are that we're going to fill out together okay so first of all what data are we working with here so back in lesson two and lesson one we were talking about a person entity same thing here person entity these attributes are the same which i've defined i've generated the uh actually before that i've set the code gen to manual and none that means i have to manually generate the sub classes and you can see that i have done that here so here's my class there's nothing in here and these are the properties mapped to the attributes okay so what does the ui look like if i go to the main.storyboard you'll see that i have a table view which i'm going to use to display all of the people in our database and then we have an add button up here which i'm going to show an alert or a pop-up with a text box where we can type in a name and that's going to add a new entry into our core data database we're going to be able to swipe each row to delete that person from the database and finally we're going to be able to tap on a row and pop up that alert again and be able to edit the name and then save it so that's updating data now i do want to mention that in this lesson i'm not going to explain how table views work and how you know a lot of this ui is constructed because we've gone through a lot of this stuff in previous lessons if you haven't seen those or you're still confused about table views and protocols and delegates and stuff like that and how the table view gets data from the view controller do visit my other lessons especially the 29 day beginner challenge which i'll link to i'll put a card up on the screen so let's dive into the view controller and let me show you some of the code we're going to do retrieval first i'm going to show you how the table view gets the data and then we're going to hook that up to core data so this items property right here this is the array of data that is powering the table view as you can see now it's not set to anything but that's where we come in and we're going to hook it up to our core data data so we're going to start at the top by getting a reference to the managed object context remember from the previous lessons i explained that you don't work with the core data persistent store directly there is a layer called the managed object context that you interact through to save and retrieve your data so how do we get a reference to this managed object context well inside the app delegate here you see this property for persistence container so we're going to get a reference to this which is going to give us the core data persistent container and there's a property on this object which gives us the managed object context so up here we're going to say ui application dot shared dot delegate and we're going to cast that as an instance of the app delegate and then we can access that property i just showed you called persistent container and then a property off of that called the view context this is the one we're looking for the ns manage the object context so we're going to keep a reference to that and we're going to call it context up there and that's going to make it easy for us to basically use the context to retrieve and save we're going to be using this reference a lot okay so down here in the view did load this is standard hooking up table view stuff there is this method here called fetch people and that's this method right here as you can see it doesn't do anything right now but we are going to fetch the data from core data to display in the table view all right so the way we do this is context dot fetch and you can see here that first of all it throws an error if it cannot fetch what you're asking it to fetch then it's going to raise an error so we do have to wrap this in a do catch block and handle that error but you'll notice that the other thing it accepts is a fetch request now we're going to start by putting in a very simple fetch request to say retrieve all of the people objects but in the next lesson we're going to take a look at other types of requests that you can do to sort and filter all right so let's choose one of these and let's choose this one right here i don't think it really matters right now and i pointed this out to you in lesson one or two but you can see here that it's got a a static or type method here called fetch request and this actually returns a fetch request for all of the person entities in core data so this is the method that we're going to call of the person class to generate a fetch request that we're going to pass into the managed view context so let's take a look at how that works so since it's a type method i don't have to declare a new instance of person i just go person dot fetch request like that all right so i'm passing in a request to grab all of the person objects in core data and we can either you know we can either do the try keyword like that to not care if any errors get raised or we can actually handle the error properly so you know we're going to do a do catch block like this and again i'm not gonna explain or cover this in depth right here since this lesson is sort of a little more advanced so essentially we are trying to uh trying to fetch this so we are going to assign the results it's going to be an array of person objects we're going to assign it to this property up here so self dot items equals we're gonna try so after all of the items get fetched then we assign it to this array we gotta tell the table view to um refresh or reload its data so that's what we're gonna do here table view dot reload data now i'm going to do this in the main queue because sometimes we're going to be calling this fetch people method from a background thread so the way we do that is we use dispatch queue.main.async and this is going to um because this is ui work when you reload the table view it's essentially going to fire all of those methods to grab the cells and stuff like that and that's ui work so we want to make sure that we're doing that in the main thread and just in case you're not sure about why it's really the main thread that should be updating and handling the ui when you start trying to do that from the background then a background process or thread then you might start getting performance impact or hits okay so just from doing that we should be able to see something because i do have a single person object inside core data right now so if i run the project you're going to see that it indeed goes to fetch data and we have one entry and it's just placeholder right now yeah just ignore that for a second the reason why it says placeholder is because for this self or row at method i just set the text of the label for that row to placeholder but we're going to i guess we could change that right now so we're going to get the person from the array uh let person equals self thought items and we're going to pass in index path.row and that's going to give us the person and then in here we're going to say person dot uh name this is an optional so i'm just going to force unwrap it and we'll grab the name so let's run it again and instead of placeholder text we actually see the name of the person object all right so now that's fetching data from core data it's as easy as that except that right now you can only fetch all of all of it you don't know how to sort of sort and filter but we're going to cover that in the future all right now for adding data how do we add data right now when we click this button i'm just popping up a pop-up to ask for the name of the person and we're going to create that new person object and add it to core data all right so that's this button handler right here add tapped so all i'm doing here is creating a new pop-up you can see here i'm adding a text field and then i am writing a submit button that says add right and when that add button gets tapped on so if we go back here you know they'll fill in a name like joe when this add button gets tapped on this is the code that's going to get run all right so how do we access the text in this field well the alert since we added a text field to the alert through this add text field method we can access the array of text fields like this alert dot text fields and we can access the first one because there only is one we only did this once right so that's our text field right here and here we're going to create a new person object and then we're going to assign the name and the age and the gender and stuff like that all right so let new person equals and we're going to try to create a new person object like usual by using these rounded brackets but you'll see here that because this is a subclass of ns managed object right that's what allows it to be saved into core data like we had talked about because that's the case you'll see that i have this option right here right to create this person object in a specific context right and accepts a parameter and let's manage the object context well we're going to pass in the context that self.context we're going to pass in this context up here right that's how we're interacting with our core data persistent container right so where was that code right here so just like that we've created a new person object in that context and now we're going to set some properties for it so newperson dot name is equal to text field dot text and this is that text field right there in the pop-up and for the age i'm just gonna set it to some arbitrary number same thing with gender but i assume that you would you would ask for all of this data you know when you're adding a new person okay so just creating a person object in the context is not enough to save the data you actually have to save it if you don't save it then the next time you run it you won't actually find this person anymore it doesn't get saved into core data so the way you save the data is through the managed object context so self.context dot save and that's simply it notice that this method also throws right so you can do you can you can wrap it in a do catch block and you know try to catch an error if there's a problem saving it so you have to put a try keyword in front of the throw method you can do this and try to catch the error if there's a save data error or you can simply not care if there are errors or not and do that if this were an actual app i would definitely try to catch all the errors and respond to and let the user know that there was an error in saving the data and all that all right so saving the data and then we have to refresh the table view because we've um all we've done now is create a new person object and we've saved it to core data but that doesn't change this array which the table view is reading off of right so i'm going to call the fetch people method right here self dot fetch people and just in case you don't remember about this fetch people method if i scroll up here it all it does is it hits the managed object context passing in a person fetch request to grab all of the people object back assigns it to this property which the table view is reading off of and then calls tableview.reload to reload the data and good thing that this puts it on the main thread because we're calling it from a background thread right here and this is a button handler from the submit button okay the last thing to do is add the button to the alert and then to present the alert so let's run this code and we should be able to add new objects to our database so let's say joe when i hit add what's going to happen it's going to create a new person object in our object manage object context it's going to save the context thereby saving the object into core data and then it's going to call fetch to fetch that data back from core data or fetch that fetch joe back from core data so add boom we got joe nice all right so now let's do delete so i i did this it's just a swipe action on the table view row it's actually very easy to do down uh where was it right here trailing swipe action so that's what we're configuring so we're going to create a new swipe action all it is is a ui contextual action and uh the style is destructive since it's going to be a delete function the title is delete and then here is the handler the code for what happens when you trigger that swipe action so first let's get a reference to the person object that we want to remove so let's person to remove equal self dot items all right and as a parameter it tells you which row was swiped on here so index path dot row okay that's going to give us the person to remove this is optional so let's unwrap that okay so now actually to remove the person and again we do these core data functions through the managed object context so self.context dot actually delete object and you just pass in the object so here we're gonna pass in person to remove and again you have to save or else it's not gonna take effect so view dot context dot save again it throws so you're going to wrap this in a do catch and catch that error if there was an error in deleting in the deletion save the data and then refresh the data here self dot fetch people all right so let's run this and test that out so let's delete joe delete so he's gone and if i rerun my app you'll see that we only have ted okay so we can add another person sammy to replace joe okay so now the last thing is did select row when we let's say select sami all i'm doing here is throwing up a pop-up same idea with the text field let's take a look at the code we have here did select row here i'm just getting the person that was selected through this parameter that that indicates which row was tapped on and then i'm creating an alert i'm adding a text field and i am getting a reference to that text field from here and i'm pre-loading the person's name all right the selected person preloading his or her name into the text field so that when when it brings up the text field we have the existing name in there already and then i configured a save button so you can see here the handler when that gets tapped that is where we are going to edit the name so the selected person we got a reference to it up there already dot name is equal to whatever name is in the text field now you know assuming that person did actually change the name and again save the data and then finally refresh refetch the data so let's run this code right now oh and the last thing i did was add the save button to the alert and then present the alert when upon tapping of a row okay so let's tap on sammy and let's save save sami as joe so now when i relaunch the app you can see that it's ted and joe so just to do a quick recap on all four of the operations we talked about in terms of fetching you call the fetch method of the managed object context and you pass in a fetch request now that could be a fetch request for all of the objects of that type or it could be one that's sorted and filtered upon which you'll learn in a future video in terms of inserting people or or adding new data what you do is you create a new object in the context right and then you call save and then for deleting you call the delete method of the context then you pass in the object you want to delete from core data and then you have to remember to save it and finally for updating you simply change whatever you want to change on that object and then you save it all right so now you learned how to create retrieve update and delete data in core data in the next lesson you'll learn how to sort and filter the results that you get back from core data all right i'll see you there hey code crew in the last lesson you learned how to create retrieve update and delete data from your core data database in this lesson we're going to learn how to filter and sort our data so that you can retrieve only the results that you want from your core data database now filtering allows you to only return the results that match a specified criteria while sorting allows you to return your results in ascending or descending order based on an attribute that you specify all right let's jump into xcode so here we have the xcode project that we worked on in the last lesson and just as a reminder in this fetch people method we were retrieving all of the person objects from our core data store through the managed object context if you remember we don't interact with the core data persistent store directly right we create retrieve update and delete data through the managed object context so that's what this variable refers to context.fetch and that fetch method is how we retrieve data from the core data store now you have to pass in a fetch request into that fetch method and this fetch request actually indicates what you want to retrieve you know how it's sorted what sort of criteria you have for retrieving the data in this particular case we wanted to fetch all person objects and so we just passed in a fetch request as is now where did this fetch request come from if you take a look we're calling a class method called fetch request on the person class so let's go into that and take a look at what it is let's go into this person class here as you can see here this is the fetch request class method and what is returned from this method is a new nsfetch request object and the data type of the data returned is set to the person right and that is what gets returned right and so it's essentially going to fetch all person objects in order to filter and sort we actually have to set some properties on this fetch request before we pass it into this fetch method so why don't we instead of putting in the fetch request here let's declare a variable or constant up here and move this line of code and just have the fetch request up here right and then we're going to set the filtering and sorting on the request and then we're going to pass the request into the fetch method now you're going to get an xcode error as you can see here ambiguous use of fetch request so you actually have to indicate the type that this is an nsfetch request and the data type that it's going to return is person so now that we have a reference to the request up here let's take a look at how we can do filtering first i'm going to run the project so that we can see what data we're working with and so we can decide what data we want to filter for so as you can see we have four names here i am going to just do a simple filtering for only person objects with the name ted all right so let's go ahead and stop the project now to filter based on some criteria we use this class called ns predicate which lets you define different sorts of conditions in a very easy to understand sort of text manner you'll see right here so let i'm just going to call it i'm just going to call it pred equals ns predicate and we can define we can use this one or we can define a format and pass in the arguments so because we want to define criteria based on the name property of the person class let's take a look here so you see it's got a name property that's where you saw the ted the joe the abbey the mic so i'm going to specify this string where i'm going to say the name property contains ted like that and you have to put this criteria here in single quotes and then we have to add this predicate to a property on the request so the fetch request actually has a property called predicate where you can pass in the criteria that we just defined and just like that if i run it now it's going to only return person objects where the name contains ted and i will show you a couple of different examples of sort of what you can filter on in a second and how you can combine different things and use different operators here so let's run the project to quickly see what we have so as you can see here it's only got the person ted now now you saw earlier how i was configuring this format and there was a second parameter because typically the thing that you want to filter on may be dynamic right this you might not know this beforehand so you can't actually code it in like i have now so in that case what you do is you put in a sort of wildcard character and that is defined by percentage at and then you can do comma here and then you can specify whatever variable contains the thing that you want to filter on now i don't actually have a variable to indicate what i want to filter on so here i can just put an example as a string but if you had something that you wanted to filter on you can specify a wildcard in your criteria and then indicate that dynamic variable here now let's take a quick look at some other ways you can define your criteria using ns predicate so here i have the apple documentation for the ns predicate class there are some common examples i'll go through with you in the overview but there's also a detailed guide that you can go through called the predicate programming guide i'll provide all these links below the video this guide if you want to really dive deep into how you can express your queries using ns predicate definitely take a look now some of the more common examples are contains which is the keyword we just used there's also equality with double equal signs and you can use like here's contains you can ignore case and diacritics which are the accents on top of letters if you want to ignore both of them you just put a angle bracket and sorry square brackets and you put cd to ignore both or just c or just d to ignore these respective things you can also combine different conditions together just like an if statement using or and and and there are different keywords to express time and you can use math inequalities like less than or greater than and so on and so forth so definitely give these things a look if you are trying to express some sort of query and you're not finding the right way to write it i'm sure a quick browse through this predicate programming guide will give you some insight on how to express that query again links to these documents below the video all right now let's take a look at sorting now similar to how the ns predicate class is used to define your criteria for how to filter the ns sort descriptor class is used to indicate how your results should be sorted let's go ahead and create an ns sort descriptor and indicate that the names should be sorted in alphabetical order now let's take a look before before we do that let's just comment out this predicate and i'm gonna run the project again so that we can see how it's sorted naturally first so you can see here it's joe ted mike and abby and it's it's not an alphabetical so i'm going to want to sort it in ascending order so let's go ahead and create a new sort descriptor ns sort descriptor and as you can see here again you sort by a particular attribute or in this case they call it the key and we're going to specify ascending is true or false so i'm going to sort by name and i'm going to say ascending is true and now just like with the predicate we have to set it to the request so request has a property called sort descriptors and if you take a look at the type it's actually an array of sort descriptors the reason for this is so that you can specify multiple levels of sorting for example a list of names is usually sorted by last name but however if two people have the same last name then their first name is used to determine who comes first so in this case since we only have one sort descriptor we still have to pass in an array however it can be an array of just our single sort descriptor like that all right now i'm going to run the project and you'll see that it's going to be sorted by name in ascending order as you can see it's abby joe mike and ted now before we end this lesson i want to point out a few more useful properties of the nsfetch request class that you can use to customize your fetch for example you can limit the number of objects that you return using fetch limit you can also start the result set from a certain offset such as this property right here and you can choose to only return specific properties of the objects and much much more so i'll link to this article or documentation below the video alright so in this lesson you learned that you can customize certain properties of the fetch request before passing it into the fetch method of the managed object context specifically you can specify a predicate using the ns predicate class and you can specify sort descriptors using the ns sort descriptor class alright i hope that was helpful in specifying how your objects get returned from core data in the next lesson i'll show you how to specify relationships between your different entities in your data model hey code crew in the last lesson you learned how to filter and sort your data using the predicate and sort descriptor's properties of the fetch request in this lesson you'll learn how to specify relationships between your core data entities alright let's get started if you remember in lesson one of this core data series i showed you a diagram that illustrated what an object graph is we had the person objects and a family object and the family object held an array of person objects we're going to recreate this relationship in our data model let's go into xcode so here's the data model for our core data entities and the first thing we're going to do is to add a family entity so go ahead click add entity and let's change this entity name to family the other thing we're going to do is let's just add an attribute called name and change it to string finally here's the part where we define the relationships between our different entities so we're looking at the family entity right now we're going to hit plus under relationship and we're going to name this relationship and what ends up happening is it's going to be a property just like these attributes are so i'm going to call this people and it's going to essentially store all of the person objects that's part of this family so the destination is basically the data type i'm going to choose person and inverse here there's nothing to select for now but we're going to talk about that in just a second so first of all let's go over to the attributes section of this relationship and specify the type and change it from 2 1 to many and that means that this people property can store multiple person objects essentially it's going to be an array of person objects now let's go over to the person and we're also going to specify a relationship here but in the inverse so it's going to define that a person belongs to a family so under relationship hit plus again and for this property i'm going to call it family and the destination is essentially the type of this property it's going to be family and for the inverse if you pull this down now you're going to see that there is an inverse and this is that relationship that we defined here right in the family entity so that's what we're going to want to select and then if you go back to the family entity under this relationship you're going to see that this inverse has automatically been set for you right and you can specify that the inverse of this relationship is the family property of the person object and the reason we specify this inverse is so that core data can maintain the data integrity of our object graph even if you're not going to use the inverse for example you know you want a family object to hold multiple references to different person objects but you don't really care that a person object has a reference back to the family object you should still specify this inverse relationship in your data model again this is something that apple recommends that we always specify this inverse relationship so that it lets core data maintain the integrity of the data all right now that we've specified this simple relationship between our family and person entities let's go ahead and regenerate our our classes actually i forgot for this family entity i'm going to set it to manual code generation as well just like i have for the person and since it's set to manual that means we have to regenerate these classes every time we make a change now first of all i'm going to go ahead and delete my existing person class because as you can see it doesn't account for that relationship that i just added so let's go ahead select both of these and choose delete and move it to trash now i'm going to choose editor and i'm going to choose create ns managed object subclass select the data model make sure that my entities are selected the ones that i want to generate the classes for hit next and let's just save it right there now i'm going to drag all of these into my model group so one of the first things i like to do after generating these classes is press command b just to make sure that everything builds successfully and if you get a failure sometimes it's just because xcode's detecting some artifacts that should be gone in the build folder so what you do is go to product and hit clean build folder and that will usually do the trick and you can press command b and build it again just to make sure that everything is fine and also sometimes xcode won't detect your new classes and you'll get some weird autocomplete errors and you'll see some xcode errors even though you can run the app successfully if that happens to you usually quitting xcode and restarting it will do the trick and that's what happened to me the first time i was working with this so i just thought i'd mention it now what i'd like to do is just to review the classes that were generated and point out some of the differences to you based on what we edited in the data model so taking a look at this person class now we have a family property you can see that the data type is family so this is a reference from the person to the family the inverse if we go to the family class you can see that here's the name attribute that we specified and here's also the people relationship that we specified the data type is actually an ns set it contains a set of people but take a look at this down here there are a couple of methods so there's two methods it's called the same thing add to people but this is allowed because the the signature is different all right the the parameter that you pass in is different one is for adding a single person object to that set here and this one is if you want to add you know multiple person objects to this set same thing goes for remove remove a single person or remove a set of people now i think you can guess that it's pretty straightforward to specify this relationship and that's why i didn't really modify the user interface of our existing demo app to accommodate families and to specify relationships between people and families because the work that it would have taken me just to create that all of that new user interface it's much faster for me just to demonstrate to you and show you the code for you to create a couple of these entities specify the relationships and save it to our core data database so let's go ahead and do that i'm going to go into our view controller and maybe i will um i'll just do it in in a random method here because i don't want to i don't want to confuse you by writing it in some other method so i'm just going to say uh relationship demo and just create this new function here or a new method here for us to write this code so let's create a family create a person and then lastly we have to remain remember to save save the context okay so let family equals so we're going to create a new family object in our managed object context so that's the context we want to create it in and why don't we go ahead let's set that to var actually because i want to change the name let's call this the abc family and let's create a new person in this context as well and oops let's set the person's name to maggie okay so how do we specify a relationship between the family and the person well there are actually two ways you can do it because we actually have relationships or properties pointing both ways so very simply you can set the family property of the person to this family up here and just like that you've specified that relationship um after you do that when you try to access family dot people you'll find that maggie is actually in that set right and you're gonna have to save it so context dot save so that's the first way you can specify the relationship and as you can see super easy the second way you can do it is by using those methods that i showed you see add to people and obviously you probably have to do this down here you pass in the person and actually we can use let for this and so that's the second way using any of these two ways to specify relationships between your objects and building your object graph like that after you save it to core data and you bring it back those relationships will get maintained right so if you bring back this family you'll be able to um look through the people and find maggie and likewise if you only bring back maggie from a core data fetch you're going to be able to access this family object through the person.family property like that all right so that's the end of the core data series for now you know just enough to start applying this knowledge and using core data in an app now having this core data knowledge is already going to open up a lot of app possibilities and ideas that we can build together on this channel if you don't want to miss it please make sure you're subscribed to the channel by hitting that red subscribe button below and lastly if you enjoyed this series and you learned something new please give this video a thumbs up it really helps with the youtube algorithm and getting exposure for this series finally i'll leave you with this what kind of app are you going to build with these newly found core data skills let me know by leaving a quick comment below alright i'll see you in the next lesson
Info
Channel: CodeWithChris
Views: 38,988
Rating: undefined out of 5
Keywords: core data, coredata, core data swift, core data swift 5, core data relationship, core data tutorial, core data 2020, core data ios, core data apple, core data vs sqlite, when to use core data, coredata entities, core data database, what is core data, app development, database, swift programming, ios development, codewithchris, code with chris
Id: O7u9nYWjvKk
Channel Id: undefined
Length: 70min 57sec (4257 seconds)
Published: Fri Aug 21 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.