[MUSIC] We've really given you enough information that you can go ahead and get started on your peer review assignment for building an application that uses CoreData to securely store your user's data with the SQLite backend and using the managed object context. But I wanna go ahead and follow through on the example that I started with, showing you how to use a picker and then how to establish objects that have relationships with them, as well. So what we're gonna do in this lecture is show you how to build a picker element where we're going to dynamically change the content within it. What we're gonna build it on is we're gonna built it on the chores that our user is entering. So in this demo what we're gonna do is we're gonna walk through adding a picker to the user interface. That's pretty easy. That's just drag and dropping. But then what we're gonna do is we're gonna handle a new class in order to handle the picker. So for a picker to operate, it actually has to have an object that you write that's gonna answer a bunch of questions that the user interface needs to ask about the picker, about how many elements are in it, how to draw it, etc. That the class that you make is going to answer questions so that the user interface can draw the object. That will also enable us to change the choices that a user has as they enter things into their CoreData. We're gonna initialize the picker with CoreData that's in the system using our fetch mechanism that we saw previously. And then, we're gonna go ahead and duplicate it and make a similar one for the chore picker. So let's jump in. Let's go to our project, where are we? There we go. And the first thing we're gonna do is we're gonna add the UI element to our user interface. So we're gonna go ahead and do that. Choose a picker view, now a date picker is a specific kind of picker that will pick a date for you. We don't actually want a date, we just want a picker for our data. So we're gonna place it, and then I'm gonna scale it to be half size. Again, Sam is rolling over in his, well, he's not in a grave, but he's upset that I'm making such an ugly user interface. I'm sorry, Sam. So what we're gonna do is we're gonna put some constraints on here. We will make it the same width as that. And we will make it about the same vertical spacing. And we'll just lock the height down. Or, yeah, we'll just lock the height down. That created a picker in our user interface, but even though there was stuff in it there in the little sample, there's nothing in it when we run it, so if we were to activate it now, our simulator should come up, and there should be nothing in it, if my worldview is correct. See how that comes up. Great. So there is a picker but you can see there's two lines but there's nothing in it. So the next thing that we wanna do then is we want to create a class that's going to be able to support that picker. So let's go ahead and, before we do that, let's add a property so that we can work with it. We'll call this the Chore Waller, good. And we're gonna need to create a new class over here in our project in order to handle it. So we'll do New File, and then what we're gonna make is gonna be a Coca Touch class. It is going to be called, let's call it the Picker, capital letter for standard convention. Call it the PickerViewHelper. And it is going to be a subclass of the UIViewController. It's gonna be Objective-C, and it's gonna be pretty straightforward when we create it. But what we need to do is we need to have it, here we go, we got it over here. So go to that header file. What we need to do is we need to implement a few interfaces. This is a way of specifying that this class is able to handle the questions that the operating system is going to ask it, and this just guarantees that our class has a few methods that can be used to answer those questions. So you, the two interfaces we want to implement is UIPickerVewDataSource. That's gonna establish this class as something that can provide data for the roller. And the other one we want is UIPickerViewDelegate. And that is going to be one that says that this can answer some other questions about it, as well. Here we go. We don't need that, cuz that's just the definition. Great. So now what we need to do is we need to go in and we are going to create some methods to help us answer those. So we're not gonna do anything with these. We're not gonna do anything with these, so I'm gonna go ahead and delete them for clarity. But what we are gonna need is, we are gonna need a local variable to keep track of our choices. And so, what we'll do is, we will have, create a property. Which is going to have an array. And the array will be our pickerData. And that is going to be the place where we keep the elements that are going to be used to display in our picker view. The next thing that we're gonna wanna do is we're gonna Override our initialization function that all classes inherit from NS object have. So that initialization function, what we're gonna do in it is we're going to make sure NSArray has something in it. So that when our first time that user interface calls our picker view helper to get the information that even if there's nothing to choose from, it won't give it an empty array back. So we're gonna Override the init function. And when we Override the init function, the first thing that we need to do is we need to make sure that we call, this is an example of inheritance. And what we are doing is we are going to, usually we would inherit the init function. So that if we created an instance of this PickerViewHelper, and we passed it the message init, if we didn't implement init ourself, it would call the superclass, which in this case would be UIViewController. What we're gonna do is we're gonna write our own init, and so when someone calls init on our object, we're gonna answer that. But, because we also want the functionality of our parent classes, the class that we inherit from, we're gonna first call our parent classes init. And the way we do that is by passing init to our superclass. Now, it's possible that something could go wrong, so if we don't get back an instance of the parent object, then we're also gonna return nil. On the other hand, if the super's initialization went okay, then we are going to set self.PickerData to a new empty array. And in fact, we don't want this to be an immutable array, because we're gonna add things to it. So we're gonna make it an as mutable array. And that means that we're going to have to explicitly create NS mutable array. ArrayWithArray. We gotta spell it right. And then, the initialization function needs to return something and it's gonna return this object, because that's what initialization functions do they return themselves. Okay, we're getting a yellow warning there, because we've declared that this function implements those interfaces. But we aren't actually implementing those interfaces. So let's just take a look at what it says. It says, oh. Here's an example of. Here's two different methods that we said we were going to implement. But we're not implementing. So, we need to go ahead and do that. I want to actually build some elements, some methods that are gonna help us first though. What I want to do is I want to set up a way of setting that pickerData array. So we're gonna go ahead and create a function called setArray and it's just gonna take an NSArray. We are going to set our pickerData equal to a new NS MutableArray arrayWithArray:incoming. So what this function is gonna do is it's going to reset our array. The next thing that we want to add is we want to add the ability to add one element to our array. This should be a, pointer. There we go. And we'll say that this is just going to be addItemToArray. And we will add something that inherits from NSObject. And we will say, self.pickerdata and add an item to it and send it a message to add data. Okay, and the Gosh, I don't do a very good job of spelling the first time around, do I? And the last thing that we're gonna do is we're gonna have a function that's going to return a specific element of the array. So we'll say get item from array and what we will have is an n s integer which is going to be the index in the thing that we want. And so we will say, self.pickerdata, and we'll say object at index, index, and we will return that, and that is gonna be sum NS object. Something that inherits from NS object. All right. Again didn't spell my type correctly. There we go. How's that? All right, so these are each functions that I wanna implement that are gonna help me out in making my roller. They're not publicly available yet so let me move them over to the interface and declare them. All right, now let me go about trying to answer this question about the functions that are required for the picker view that I haven't implemented yet. Now the picker view is going to need some information. It's going to need to know how many items are in the list. It's going to have to know what the different items at various elements are. What it should display for those different elements. And yeah, so right. So let's go ahead and implement them. So the first thing that we're gonna need to implement is one called, and the way that I know this is because if you go to the documentation for the interface, you'll see the different ones that you need to implement. So it's gonna be pickerView UIPickerView number of rows component. All right, here we go. And, what this is asking for is, it's asking for how many elements there are in our picker view. And, so, that's pretty easy because we're just gonna say our pickerDataCount. PickerDataCount is gonna be the answer. All right. And the next one we need to answer is. Let's see, we need to answer the data that we're gonna return for a particular element. So what we're gonna do is we're gonna say, right we have to return strings that are gonna fill out those roles, fill out those rows in the picker view. And so that we're gonna do picker view, picker view title for row. Yeah, that's good, no we need to and the row is the number we care about, so we wanna get back is we wanna get, we want to create something that is based on the number, based on an element in the array of picker data. So if we, if the picker view is asking for what it should display in row zero we want to get substring that represents picker data sub zero, so what we'll do is we'll just say, pickerdata sub object at index row. And then we will ask for the description element. Now remember, the description is what would be passed back if there was a %@ sign in a formula. And so whatever we're keeping track of, we're going to send the description of it back as what gets put in the row. Right, now, if all goes well, we have implemented some of what we need to implement. There's still a couple more that we need to make sure that we have. And we can check right here and what does it say? Number of components in picker view okay, so it's asking us how many columns in this case do we have, so it's gonna be NS integer and it's gonna be numbers NumberOfComponentsInPickerView. And when it says this, what it is asking is how many columns. You know like on a date picker, you pick the day and the hour and the month, and the AM / PM. You can pick the date, the hour, the minute and the AM / PM, and stuff like that. That'd be multiple columns, we're just gonna return 1 for our example here. Okay, all right, and with that, we have implemented everything that we need to implement in order to, for this to be, to support our picker view But now we need to use it. So meanwhile back in our view controller, let's go back to our story board. When we first create our Our element. We're going to need one of those PickerView helpers in order to keep track of the elements that are in our PickerView. So let's go ahead and make a property where we can keep it. And it's going to be a PickerView Helper, and we will call it chore roller helper. And we don't know about it because we haven't imported it. All right. There we go. All right, and then when we initialize, Our function, let's see, where are we? In addition to updating our LogList, we wanna update our Picker. So let's go ahead and pretend like we have such a function, we'll call it update chore role. And then down here by update log list we'll go ahead and like, we're gonna wanna use some of this codes, let's go ahead and do this. And let's say void, it's copied from the update log, void updateChoreRoller, no parameters. All right, the reason why we're gonna be looking at our core data fetch is cuz we need to get the element set from core data that are going to be put into our list here. So, we're gonna get our managed object context. We're gonna go through each of our chores. We're going to execute a fetch request. We're gonna get back some results, and as we go through the results, we're going to want to add some things to an array, so let's make an NS. Let's see. I don't have enough space here to clearly show you what I'm doing, so I'm gonna make a little bit more space. More space. Thank you. All right. And we update our chore roller. We get our managed object context from our app delegate. We create a fetch request to fetch things from the chore entity. We actually fetch it and check for errors. Now we're gonna create a new NS mutable array which we're going to pass to our chore roller helper to be the source of our data. And we're gonna just start it with an empty array. Right so rather then filling a string we're going to go through each of the elements in our result. And, oh you know what, actually we don't need to go through each element in our result we can just say array with array, results. Okay, so that's gonna get the data we care about. Now, we need to add it to our chore roller. So we'll say choreRollerHelper, we'll say, not add, we wanna set our array equal to the chore data that we just captured all right. I always forget to put self, all right and that's good to go. Once we've done that we need to also make sure that self dot chore roller, we're going to need to reload all components. That's going to refresh it. But you know what, this is good. We've set our chore roller helper and we've reloaded our chore roller, but we never attached our chore roller helper to our chore roller. And that only needs to be done once, and so we should be doing that up here. When we first load our delegate. When we first load our view controller. So what we're gonna do here is we're going to send to our chore roller, we need to do set delegate. And that's gonna be our chore roller helper. Because it implements the picker delegate interface. And then we also, because we have the option to separate out the delegate and the data source, if we want. We're going to do that. And again, I forgot myself. I forget myself. I forget myself a lot. I'm very selfless. All right. I forget myself again and again, and again. I need to take time for myself. All right. All right, so let me just walk through what's happening here. We create our view controller. We connect our chore roller user interface element to the chore roller helper by setting the delegate of the chore roller to be our chore roller helper. We also connect our chore roller to our chore roller helper by setting it as the data source. Then when we come and we update our chore roller, we go ahead and we send the data that we have in our persisted data set here, we fetch it from our core data. We put it into our chore roller helper, and then we tell chore roller to refresh with all the data that we just got. Now if all goes well, okay. Pick up again. All right. So I made kind of a dumb error. In my initialization, I defined a chore roller helper but I never actually created it. So all I have to do is do self, dot chore roller helper, equals, a new picker view helper. Allocate it. And init it. I just never created the object. So I get the delegate, and then I create the chore roller helper, and then the chore roller has already been created by the UI, and so then I connect the chore roller to the chore roller helper. And then I update the chore roller. So I was just trying to update a nil element the whole time. There we go. All right. So now we've got our roller that you can add elements to. We add a chore and wash the car gets added to our roller. Okay. That's good for our chore element and now we need to do the same thing to add a person element. So we're going to come back here, and we're going to walk through the steps to do that. If we go to our story board we know we need to create a new. That's not a link, need to create a new text field, and we need to create a new button, and we need to create a new picker, and we need to make to make sure that they have the appropriate names. So we'll come over here and we'll say, what do we have, we have a chore field, and so we want to duplicate that and we want to have a, we want to have a person field, and if all goes well we'll be okay and then we need to connect that to our person field, good. This is going to say Add a Person. It's going to be our button, and so we have a chore roller and a chore roller helper, so we're going to need a person roller, and a person roller helper, and we're going to attach our person roller to the person roller. Good. And we know that, in addition to choreTapped, we're gonna have something that looks like personTapped. And rather than creating a ChoreMO, we're gonna create a PersonMO. And that's gonna create a PersonMO, item, okay that's P. We know that we're going to be setting the P person name not to the chore field, but to the personField.text. We're gonna save that new object that we've just created. We're not gonna update the chore roller. We're gonna update the person roller, and we are not gonna need to update the log list cuz the log list right now has chore elements. All right we go back to our initialization when we initialize we don't have to do anything else. We need to create our person roller helper, that was a mistake we didn't do a chore roller. So that's going to be another instance of a picker view helper, and we need to connect our person roller to our person roller helper. Okay. And our person roller helper is what we're going to connect that to. Then, in addition to updating our chore roller, we're going to need to update our person roller. Chore tapped is okay. Person tapped hasn't been connected but we'll go ahead and connect that there. We have still a little confused. Because we haven't created an update person roller yet. We need to do that. Like I said, what we'll do is, we'll just copy update chore roller and make a version that is update person roller. So we're gonna get the same managed object context. Instead of going through chores, we're gonna go through the person entity. And we're fetching person objects. Up here, this should have been chore objects. Okay. We're going through our person elements. We're not creating chore data. We're creating person data. Just so we don't get confused about what's happening. Each of our results is going to be a person MO. Our person data. We'll get the object added which is P. And, person roller helper, we will add our person data. And then finally our person roller. We'll relay to all components. Okay. So we have duplicated everything. The only thing we haven't added is constraints for the user element, for the user interface. Let's see if we can just add some ugly constraints here. Add a constraint that keeps it on the right. Then we'll add a constraint that keeps it on the right. And we'll add a constraint that keeps this on the right. We will make sure that these are horizontally, or centered vertically. Make sure these are centered vertically, make sure these are centered vertically. And we'll make sure that these are the same width. We'll make sure that these are the same width. We'll make sure that these are the same width. And actually, we'll make sure they're the same height, as well. And now if we run it, hopefully we will have duplicated our person functionality. All right, they are horribly overlapped, and I don't like that but let's see what we get. Let's add Dad. The interface is a mess, but what we forgot to do is we forgot to add a description method in our person class. Let's do that, and then see if we can fix our mess of an interface. All right. In our chore class, we have an example of a description. We're gonna take something very similar to that and put that in our person class. Rather than returning chore name, we're gonna return the person name for the description. And then in the header file, we're going to declare it. And of course, we're overriding the default version that usually gets recalled, that we inherit from NSManagedObject. All right, now, let's go back to our view and see what we can do about our overlapping pieces here. What are our constraints on this item's width? That's my first question. We can see, the chore width is equal to the chore. Well, all right, so, what is the constraints on this width? Equal width to the chore field. Equal width to the person roller. All right. So, let's add a constraint between these two that make sure. Of course, our spacing remains the same. Hopefully that will be enough to cascade everything together. Eh, not quite. All right well, I'll tell you what, let's just hard code the width for now, rather than worrying too much about that. That's not the best thing to do to get this video going. We'll make it happen. Wow. This is the world's ugliest interface. For now though it's working. We've got different spinners going through the different elements. We've got. And we are updating our washing dishes drying dishes down here. [SOUND] That was a tough one. So we managed to get our pickers wired. What we did to do that is we created a picker element. So we needed to create this other class that would answer questions about the picker. Then we had to carefully walk-through the logic in our view controller to make sure that when we created our view, we populated our picker with the right values. When our values were populated, we needed to make sure that our managed classes, answered the description call, we need to make sure that our picker view answered the interfaces, and then we needed a way to update the elements that were in our roller. At the end of the day we got it working. The next thing that we're going to do is add our date roller to it and try and build elements for that middle table that has the two relations on the side. All right, thanks. [MUSIC]