Start course
2h 10m

This course focuses on a concept known as core data, which will allow us to store our data in a database. We'll then show you how to apply this concept to a real-life app which we will build called Art Book.

Learning Objectives

Learn how to create a local database allowing users to save data on their phones using core data

Intended Audience

This course is intended for beginners who want to learn how to build apps using Swift.


To the most out of this course, you should have some basic understanding of programming and computer science in general.


Hi, within this lecture, we're going to learn a concept called Predicates and we will use this to filter out the results that we're getting from the Core Data. For example, in our ViewController, we have just gotten every data on the Core Data and just printed out the names on the TableView but in here, rather than getting only the names and the IDs, I will just get everything related to one single item. So, let me delete all of this and start from scratch. I'm going to, of course, create the AppDelegate one more time. So, this will be UIApplication.shared.delegate, okay? So, delegate. Yes. I'm going to first cast this as AppDelegate and then I'm going to create my context as usual. So, my context will be appDelegate.persistentContainer.viewContext. viewContext, yes. So, this one. And I'm going to create a fetchRequest as we did before. So, I'm going to say this is going to be a fetchRequest and it will drive from NSFetchRequest. It will ask me for an entity name, not entity but entityName, like this. So, "Paintings" and we're going to have to add NSFetchRequest result in here. So far so good, we know how it's done, right? Next thing we're going to just fetch this using context. But before we go on and do that, I'm going to say this returnsObjectsasFaults is False as usual. And before we do that, I'm going to add the predicate that I have been talking about. So, I want to filter out the results so that it will only include the ID that has the selected ID. So, let's convert this chosenPaintingId to a string because we're going to need this in the predicate, okay? And in order to add this predicate, you will just say fetchRequest.predicate and it will ask you for an NSPredicate and if you write NSPredicate, as you can see this is the logical conditions used to constrain a search. So, we're going to do a fetch and in this fetch we're going to just add some logical constraints so that our results will be filtered accordingly. And in order to do that, we're going to open a parenthesis and just see the parameters that are being asked for us. And it's kind of different than what we have seen before. It's kind of regular expressions if you have worked with one before. So, let me show you what I mean. We want this format thing, we're just going to explain a format and we're just going to give some arguments. So, for format I'm just going to say, so name will be this, ID will be this, okay? Like that. So, you have to say id = %@. % and @. So, it means that ID will be equal to something and something will be written in these arguments. For example, idString. So, it basically means that find ID being equal to idString. For example, you can do this for anything, like you can just go for name being equal to nameString or chosenPainting like this. Name being equal to chosenPainting, okay? And this will work too. But if we have the same name for two different arts then it wouldn't work because it will get confused. Rather than doing this, we're just going to do that with ID, okay? And that's it, that's what will filter our results. So, if I do the fetch right now, I will only get the results of the selected ID. So, let's do that. So remember what do we have to do, we have to use the context and just say fetch and it will ask us for a fetchRequest and we will provide our fetchRequest. And remember, it returns us, it can throw an error. So, we will have to do try catch. So, let me cut this and paste here with try. Okay, try and this will return us an NSManagedObject array, right? So, I'm going to just say, let results try context.fetch. And in fact, this is not going to be an NSManagedObject as I said, it's going to be an any array, right? Any object array. So, I have to cast this as NSManagedObject array. So, I'm going to say if results.count is actually bigger than zero and it's in fact safe to do that. I believe we omitted to do this in the previous control. So, we have tried to just go into the for loop. I believe we should do that. If results.count is actually bigger than zero then we have to go into the for loop because results can actually be empty in here. Okay, if there is not any recorded value in our app, it means that results cannot go into the for loop. So, it's actually safer to use this. So, if results.count is bigger than zero, then I can just try to go into the for loop with casting this as an NSManagedObject array. So, I'm going to do the same thing for resulting results as an NSManagedObject, okay? And then, I'm going to go into the for loop. And you can say that we're just going to get one item, why are we even bothering doing that for loop? Because even though we have 1 or 2 or 1,000 items, the result will be given us within an array, it doesn't matter, it returns us and then this context.fetch returns us an NSManagedObject array. So, we have to do that. We have to go into the loop anyway, even though we have one. We can do that as well, results [0], but it won't be as safe as doing that. So, maybe we're working with ID. Maybe there is, it is certain that we're just going to get one item but I believe we should just take on the for loop so we can do the same structure in all apps. So, we can just say if let name = results.value forKey name is string as we did before, right? So, it's actually better to use consistent methods, consistent functions during the app. So, nameText.text is going to be name. So, this is what we have done before, let me copy and paste this and it's kind of distorted in here. So, let me make this right. So, rather than name, I'm just going to go for artist this time, okay? So, the key will be artist as well and this will be artistText.text. If I write everything from the scratch it will be much more easier, I believe so, let me just say, if let year is going to be result.value, the key will be year as well. Not year, yeah, year. And this will be an integer rather than string. So, this will be displayed in the yearText.text. And in fact, we're just going to convert this to be string again and maybe you can just say that, if we're going to convert this to an integer and to a string, why did we store it as an integer in the first place? It doesn't make sense to store this as an integer in this example, but I just wanted to show you how to store an integer to Core Data. So, let's go for imageData. Remember we start our image as data so I'm going to cast this as data as well. So first, I'm going to get this as data not string, not UI image, not anything but data and then I'm going to convert this to be a UI image and it's fairly easy to do that. So far, we have been doing this UI image thing and we have been selecting the name, rather we're just going to go for data this time and I'm just going to paste in imageData. So, this will take our data and convert into a UI image so that I can just come over and say imageView.image is going to be image, okay? So, that's it. That's how we're going to get the information related to our selectedPainting. So, in the catch I will just print out some error, okay? And I don't think we have to do anything else. We can just try this on our simulator and see if we can see the details and here we go. We see the waterfall, Da Vinci and for the flower, we see the Van Gogh 1900. It seems to be working, I believe that's good. Of course, we had to do some more improvements here as well. For example, we cannot delete those values. And as you can see when I click on the ads, it shows up as a default screen, so it definitely works. So, when I tap on this I shouldn't see the save button. I can see in here, it doesn't matter. But when I click on the TableView, it shouldn't pop up here, okay? And I cannot delete this right now because I don't have this kind of functionality yet. So, I believe we should stop here and within the next lectures, we're going to work on the improvements and finish our app.


About the Author
Learning Paths

Atil is an instructor at Bogazici University, where he graduated back in 2010. He is also co-founder of Academy Club, which provides training, and Pera Games, which operates in the mobile gaming industry.

Covered Topics