Core Data with SwiftUI

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
CoreData helps you manage and store data in  your iOS Apps, but it can be hard to implement.   Well not anymore. Alex here from rebeloper.com and  today I will teach you how to use CoreData in   SwiftUI. So if you are interested hit that  SUBSCRIBE button and open up Xcode and let's   dive into learning CoreData in SwiftUI. So let's learn how to use CoreData in SwiftUI.   We are going to start off from scratch. So we are going to create a brand new Xcode project.   But before I dive into this let me just remind  you about rebeloper.com/mentoring. 60 minutes of   one-on-one Zoom call with me. If you have a bug  or you want to learn SwiftUI or even UIKit go   ahead and check it out rebeloper.com/mentoring  where you will be able to meet me on a one hour,   60 minutes Zoom call. We are going to start off  with a brand new Xcode project and I'm going to   go ahead and create one. Let me just resize  this so you can see it a little bit better.   There we go and let's select iOS and App.  Let's click on next here and I will name this...   And you can just check this use CoreData but I will not. I will start off from scratch building   out all the CoreData related stuff so maybe if  you are having an existing SwiftUI project you   can use this tutorial, okay. Make sure that you have  SwiftUI as the interface and SwiftUI app   life cycle. Let's click on next and let's just  add it right over here under videos, there we go.   And let's create a new folder. I'll just name this  Code and finally let's create it right over here.   Okay! So yeah I won't to use Canvas. So I'm just going to remove that. First things first   we want to create a CoreData Stack and I'm just  going to name this a Stash. So what you want to do   is just go ahead and right click on here. Let's create a new file and let's just scroll all the   way down and you will see that we have a CoreData model right over here. Let's click on next   and let's name this Stash. You could just name  it whatever you'd like, I'm usually calling   it stash because I'm stashing away all that  data, okay. Let's create that and there we go.   We have our data model right over there. Let's move this right into that SwiftUI CoreData group and   I'm going to create two entities. One is for the  item and the other one is for categories because   we are going to link them together. So let's tap  on this plus button. Let's name this Entity Item. Okay and this item should have one attribute  and that is name and it should be a string   value, okay. Let's create the second one  and let that entity be named category. Okay and that category will have also a name. Now you will be able to add in here much more for   the sake of this simple tutorial this is enough.  Now I want to have relationships between them.   So items may be associated to categories  and also categories may have a lot of items.   So what you want to do here is go, let me  just have here much more space. So just go   under relationships. You will have  a plus button right over here   and we are inside the category so I will name this relationship to item. Okay and destination is item and let's  just go into item do the same thing.   Now I will name this two category and this  is destination is category and set this the   inverse to item and let's just go right over here,  as you can see the inverse has already been added   really nice. So this is our default data model.  What we are going to do next is just create a   persistence controller that we are going to use  throughout the app. It will be having a shared   property so you will be able to access  it throughout your app. So let's create that.   Let's just go right over here. Let's create a new file. It will be a swift file and let's name this   Persistence Controller, okay. So first things  first we want to import CoreData here. Right! And this will be a struct. Let's have this copied  out and paste it in as the name and first of all   let's create a shared static let here. So we can use it as a singleton. So static let shared equals   persistence, let's hit Command + B  so we have that auto completion. Persistence Controller and that's it.  Okay! So what we want to have here first   is actually a container. So let's see. Let's hit Command + B so I get rid of that error.   Okay! Build has succeeded. Really nice! Let's create our container and NSPersistence,   NSPersistenceContainer, there we go. So we got our container, what we want to do is just initialize it   when we are creating our Persistence Controller. So let's create an init right over here.   we don't have any parameters but we're just going  to use container equals NSPersistenceContainer   with a name and go ahead and add in the name that  you created for your CoreData Model, mine is Stash.   Okay! Once you have that initialized the container  you want to load the persistent stores.  So container dot load persistent stores with the  completion. We might get back a description but we don't really care about that or an error.  Now if there is any error we just simply want to   crash the app. You don't want to use the app if the  persistence stores weren't loaded. So if let error   equals error. Then we just go  fatal error with a message   and let's call it like error and let's  add in here our errors localized description.   Okay and that's it for our initializer. Now we have our persistence container created and loaded the   persistent stores. Now what we want to do in this  persistence controller to be accessible we want to   have a save and the delete function, okay. So let's do that. Let's start off with the save. So func save   and on the save, yes we might encounter  an error but we might not worry about it   but let's just create a completion  here with the default completion.   So completion. So yeah with the default completion  because we might not want to use it. @escaping and we might complete, let me  just add in here the full completion and   this will be, this is kind of the default value.  Let's just add it that in there. So this is our   default value and we are going to get back an  optional error. So we will get back an error.   I think we are missing some things. Let's see escaping. Yes! I just added that colon   and it doesn't have to be there, okay. So we will be completing with an error if we find any   errors or we are going to complete with nil if  everything worked okay. So let's grab our context...   ...equals container container dot managed view context, yes. It's view context and if context   has changes. So if this context has changes that  weren't already saved. So with this if statement we   are kind of ruling out that we are saving over and  over again even if we don't have any changes.   Then we are going to go and try to save our context  with a do catch statement. We are going to go   try context dot save, okay. As you saw it will throw  an error and on the catch we are going to complete.   So completion and the error, okay. If everything went okay we just go and complete with nil as I   already told you, okay. This is fine. So now we have our save let's create our delete function. So func   delete, so we will use these later on in our  project throughout. So we are going to delete   an object and that will be an NSManagedObject, there we go and we are also going   to complete like we did with the save. So let me just copy that out and paste it in there.   Okay! So how do we do that? We again we just grab  our context and that is from the container   dot viewContext and we just go context  delete our item, our object basically.   Okay! So once we delete on the object  on the context we still have to save   our view context. So we just go save and use  the one with the completion and just go completion   because the delete completion is the same as the  save completion, okay. Real nice! So now we have this   kind of helper file persistence controller let's  add it to our project. So first of all we want to   add this into our view hierarchy and we are  going to start off on the SwiftUI CoreData App   file so right over here. We are going to create  our persistence controller right over here.   So let, let's just have this as a new line. Let persistence controller   equals persistence controller dot shared, okay.  So now that we have that we want to add it as   the managed object environment. Now I don't know  if you have learned or heard about environments.   If you add an environment into your content  views or any of the views basically you will be   able to access it throughout all of your other views. So let's just go and grab environment.   Now the key path will be backwards slash dot managed  object context and this will be our persistence   controller. So this is just a controller. So we want to grab its container and the view context.   Okay! So that's our managed object content in the  injected as an environment into the content view.   Okay! This is great! So we are going to save  and delete stuff but it's a good practice to save   the managed object context when the app  goes into background. So how do we do that?   Usually we went into the scene delegate and there  we had when we went into the background so that   delegate method. Now with this new SwiftUI app  structure we are going to get the scene phase and   there we're just going to save our contacts in  the background. So let me just do this, first of   all we want to grab the scene face environment. So @environment and backward slash dot scene phase. Okay and that will be a variable called  scene phase, okay. So now that we got our   scene phase we want to listen to  it and we are going to listen to it   on an onChange of scene phase.  So dot onChange of scene, scene face, there we go. Make sure that this is on the window group.   We are going to perform equatable  is the new scene phase, okay phase and let's just switch through  all of those. So switch   new scene phase and let's just wait Xcode complain  and add the values right over there and as you can   see we have background inactive, active and we are  going to go and just print out some stuff for now. Oka! Let's just go with all of these  and scene is in active. Scene is active and on the default well that's just the future  proofing this switch statement. We want to add,   well actually we want to save on the background. So we just go and select our persistence   controller and go ahead and save. I'm just going to  use the one without the completion. I don't really   care I'm just going to save right over here, okay.  So that is one really important part so you save   your persistence container on the background when  we the app goes into background, okay. So now it's   time to take a look at the content view. So on the  content view we are going to create kind of two   buttons because we are going to create a create  a new item or create a category and we are going   to list those items in actually a list. So let's start by creating our views right over here. So first thing we are going to do is  just create a VStack and inside   that VStack we are going to add in a button.  So let's see, a button right over here, okay.   Let's just use the one with the action and label  and on the text let's just add category.   Okay! Let's do the same for our item. So let's just add it right below it add item.   Okay! So whenever we are going to tap on add item  we want to check if there are any categories.   So for that we are going to add in here an alert. So let's see, yeah let's just go ahead   and leave these as are. Let's just worry about the  list for now. For the list will be right over here   and a list I'm going to use a forEach  view, but for the forEach view I do need the items.   So let's scroll all the way up and let's create  a fetch request for those items right over here.   We do need a fetch request but the fetch request  will also need the manage object context.   So let's just import that environment. @environment and backward slash managed   object context, there we go. That will be a  variable called again managed object context. Okay! So that's our managed object contacts. Next we are going to create that fetch request. So we are   actually going to use again a property wrapper for  those items and let's just go ahead and type out   @fetchRequest, there we go and if you go open  up parentheses we will see that we have a few variables   here with an entity, sort descriptor, predicate,  animation. I'm just going to use the one with the   sort descriptors and predicate. I don't really  care about the animation. Let's see if we have, no   we don't have, yeah so let's just use this one.  Animation as you can see so predicate animation   could be optional. So I'm just going to  omit animation, okay. So the entity. What   is the actual entity? Well we are going to fetch  some items. That is important that you created that   object on your CoreData Model. So item dots  entity, okay. That's our entity. What are the sort   descriptors? Well how should CoreData give us back  this array of items and I think we should just go   ahead and order them by name. So here you can have  an array of sort descriptors. You could just have   more like sort them by name or caption or  sub title or whatever you'd like. I'm just going   to add in here one. So this will be an NSSortDescriptor, there we go and that sort descriptor   should have a key path and let's just go with  ascending. So the key path will be backward slash   item dot name. So we are interested in the name and  ascending let's set this to true, okay. Now for the   predicate yeah the predicate is well actually we  don't really need a predicate right over here but   I'm going to type it out for you. So let's create an NSPredicate and let's have one with   the format and arguments, okay. So the format  should be like let's just search for the name   and that will be equals to and the percentage  and at (%@). So that means that we the name should be   equal to the argument that we are adding it here.  So it should be equals to something, let's just see   we are going to save some clothes and the item  will be a shirt. So let's just go ahead   and add shirt. So only the shirts will appear. You know I do understand that this is not kind of what   we actually want to do right here but you know  how to use our predicates and I think we need to   not have these arguments right over here. Yes! Animation we can just safely remove that, go ahead   and check it out just add an animation how these  entities will be presented. And finally we want   to get var items and this will be a fetched  result of type items. So fetched result. Fetched result of item, okay. So this was quite long but   yeah you added the entity. Let's just add  that right over here, the sort descriptors,   the predicate and then you just named it as items.  Maybe let's just move all of these down here and this one right over here, okay. What you want  to do just select all of them and hit Ctrl +I   so it gets this nice indentation, okay. So we got our items. Let's just add them into our   list because yeah that is what we actually wanted.  Now we are going to use a forEach view and we   are going to go through all of the items, okay. The id will be self so all of them will be identical   and right over here we are going to add item in. So we are going to get back an item, okay.   So now that we got our item we just need to just  make them visible I'm just going to use a text   and I'm going to set out the item names. Now if the  item name doesn't exist then I'm going to print   out unknown. So let's just interpolate that item  dot name. If this doesn't exist let's just go with   unknown, yes we do. Yes I think. Yes I want to add that right over here, correct.   Okay! Unknown and yeah basically that is it. Let's see so this is how we add our items. So let's   tap on the button and let's add one of our items.  So let's create on the button, well first of   all I think that we should actually create  a category first so we can tie it to the item.  Okay! So again let's create a fetch request right  over there on the categories. So let me   just copy this out and have this as category, okay. Now category will be our key path   and then the predicate. Well I don't think we do  need a predicate right over here, I'm just going to   remove this and let's name these categories, okay.  So now we have access to all of those categories.   Okay! So now let's just see if there are any  categories. If there are categories then we   are going to go ahead and present an action  sheet that where we'll be able to select   the categories that we already have in there, okay. So if categories dot count equals zero   then we are going to show an alert. Else we are going  to show an action sheet. So let's just create those   state variables so we can use them when  creating the alert and the action sheet and   let's just add them right over here. So private state and is action sheet presented false by default and again a new straight  private variable is alert presented.   That will be false, okay. So what we want to do is  if the categories count equals to zero we want to   present our alert. So isAlertPresented.toggle() and  otherwise is action sheet presented we are going   to toggle that. So let's add in those two. Let's start off with the action sheet. I'm going to add   them right on this button. So dot action sheet is  presented and the dollar is action sheet presented   for the binding and the content, well the content  will actually be an action sheet but we do want to   have, I think i needed to add a dot here. What we  would do want to add all of the buttons. So let's   create the buttons first and then we are going to  add them to the action sheet and return the action   sheet right over here, okay. So I believe I didn't  have that auto completed correctly. So let me just   do that again. So action sheet is presented dollar  is action sheet presented, okay. So everything seems   to be okay. So first of all let's create an  array of buttons because there might be a lot   more than one categories. So that will be an action  sheet, there we go. Action sheet the dot button   and let it be an empty array, okay. So we go through  all of the categories. So categories forEach   and we are getting our category right over here.  So for all of those we want to create a button and that will be actually an action sheet. Action sheet button dot   button and let's just go with the default because  there might be more. You can't have more cancel   buttons. So that's why I'm choosing this and I'm  going to go with the default label and action.   The label will be our categories name. So let's create a text right over here and category dot name, okay. That should fix itself  and if that doesn't exist it should go unknown.   Okay! And what about the action? Well this is where  we want to go ahead and create an item for that   category. Before we do that let me just add a  new console button here. So buttons dot append   console dot console, okay. And finally let's  just return an action sheet so we don't don't have   that error all already in there. So action sheet  and we are going to use the one with the title and   buttons. So the title will be again a new text, okay. Please select the category. Message could be   nil, so I'm going to go with nil and buttons,  there we go. So now we won't have any errors.   So this is whenever we tapped on the item,  what's going on here, action sheet, title, buttons.   Oh! I added the return inside the completion  so that is not what we want. We want to add   it right over here also the appending  of the console button right over here.   Okay! So what we want to do here is create  a new item. So let item equals and item with a context and that context will be  our managed context that we just created   and we can just set the item dot name. Let's just have it as shirt for now. Yeah you can just   go ahead and move this forward. So you can add  multiple types of items but currently it's just   going to create one shirt and then we are going  to tie this to this category. So item two category   equals category. So this is how we kind of link  them together. Also now that we have the name   and the two categories set we can just simply save.  So persistence controller dot shared and just go   with save. I'm not going to take care of I don't  worry about the completion. I'm just going to go   with save, okay. So after we got our button we just  want to go and append that. So buttons dot append   the button right over there. Nice! So finally what  we want to do is as you can see if the categories   there are no categories we want to present an  alert. So let's do that. Let's create an alert right   over here with the is presented. We just bind it  to is alert presented and the content will be an   alert, there we go. Alert with the title, yes title  message and dismiss button. Well I'm not going   to care about dismiss, sorry about the message. Let's just go with the title and that will be a text and let's just go "Please add category", okay.  And message nil and dismiss button, let's   just go with a dot cancel button  with a label of okay. So text okay.   So yeah, so now that we have all the categories  also set up we might want to add the categories   right over here. So let's just create the  item dot to category, there we go dot name.   Okay! Oh sorry name and that to category  is an optional. So let's just have that   right over there and if this doesn't exist  then again let's just go with unknown. Okay! Yes, so now we can just simply build and  run let's select one of our iPhone 12 simulators.   Let's build and run and now we will be able to  add a new category and add a category an item    onto that category and after that we are finally  going to learn how to delete. That is really really   straightforward. So if i tap on add item you will  see that it says "Please add a category", okay. Let's   add a category, so yeah hit just save that under  the hood and now we can just tap on add item.   Well it doesn't seem to save it. Yes, we didn't save it actually. So let's go all   the way up right over here when we are adding  a category and yeah let's create a category.   It will be the kind of the same as we did  with the items. So let category equals category.   There we go and let's grab our  context managed object context and   let's add a name for our category. Name, let's go with clothes, okay and then persistencecontroller.shared.save, okay and that  should be it for our category, okay. Let's build and   run and see how this looks like, okay. So let's tap on add item, okay. Please add a category. Let's add a   category that should have saved that because we  didn't have the code actually and now let's add   item you can see that it fetched the clothes. Let's select clothes and there we go we have a shirt   under the clothes, okay. So we should be able to  delete this. So how do we do this? Well we want to   add a delete function on the list itself. So let me just scroll all the way down and on the forEach   we could just add an on delete but let me just  create our function first for it. So func remove   item and we want to remove an  item at an offsets and that will be our index set, okay. Deleting is pretty straightforward first of all we want   to know that we want to loop through all  of the indexes on that offset. So for index in offsets. Let's grab our item ,equal items  add that index, there we go and then we just go persistencecontroller.shared.delete that  object and the object will be our item.   Items and categories are NSManageObjects, okay. So what we want to go is just go onDelete and don't   you autocomplete here because it will just  add perform. What we want to do is just type out   perform and there we go. So that is it.  So remove item at offsets and let's just hit   Command + R and we should be able to swipe, there we go and if we just hit delete it will remove   that item. Really, really nice. Let's add an item  again clothes. There we go and we can just swipe   all the way out and it will delete it. So that is  it for CoreData in SwiftUI. Now you know how to   save and delete and set up your CoreData Model  and use all of those with a fetch request. So you   can fetch all of your entities, items or categories  and you can also add sort descriptors predicates.   Now if you are interested in setting up a  fetch request limit then you want to not use   the built-in fetch request, you want to create just  a simple fast request and then on the initializer   you want to add to that request a fetch limit, okay. That's it for CoreData and SwiftUI. Now if you   did enjoy this teaching style go ahead and  check out DEV_FACTORY and that is a 60 minutes   one-on-one Zoom call with me. If you have any bugs  in your code or if you do want to learn SwiftUI   go ahead and check out rebeloper.com/mentoring  where I will teach you well whatever you want   bug fixes, SwiftUI, I'm here for you. As of SwiftUI you can implement CoreData relatively simple   as you already saw. So I hope you will do so in  your next project. Now if you did like this video   go ahead and give it a thumbs up and while you  are at it make sure to hit that notification bell   to get notified of new videos as they do come  out for example take a look at these videos. I talk a lot about SwiftUI, Swift in general  and as usual I will see you in the next one.
Info
Channel: Rebeloper - Rebel Developer
Views: 11,183
Rating: undefined out of 5
Keywords: Core Data SwiftUI, core data, SwiftUI, database, save data, swiftui tutorial, core data swift, database tutorial, save data iphone, core data ios, core data tutorial, core data swift tutorial, what is core data, core data stack, core data apple, add core data to existing project, core data transformable, core data ios tutorial, swiftui tutorials, core data array of objects, xcode core data tutorial, core data swift relationships, How To Use Core Data From Scratch, rebeloper
Id: _GJlFk-Hhz8
Channel Id: undefined
Length: 36min 45sec (2205 seconds)
Published: Tue Apr 06 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.