All right. 1
So how did that go? 2
I hope you gave it a go. 3
And you now have a working CategoryViewController that works as you expect it to. 4
Now, I know I'm repeating myself, but if you haven't given it a go, do it now. 5
Don't watch the solution video first, because then you can't prove to yourself that you really do understand 6
it. 7
So I'm going to presume that you've given it a real good go and you're just here to check and make sure 8
that you've got it right. 9
So if we have a look at our To Do list view controller, the first thing we have is this variable itemArray 10
that contains an array of NSManagedObjects created using the item entity. 11
Now, over here, we'll need something similar. 12
So let's create a variable called categories that is going to be an array of Category objects, and we'll 13
initialize it as an empty array. 14
The next thing we need to do is we need to grab a reference to the context that we're going to be using 15
in order to create, read, update, and destroy our data 16
and this is gonna be the thing that's going to communicate with our persistent container. 17
So the context is going to be equal to our UIApplication and we're going to grab the shared singleton 18
app instance, and we're going to tap into its delegate property, and we're going to downcast this as 19
a AppDelegate object, and then we're going to tap into our appDelegates persistentContainer variable, 20
and then we're going to load up the viewContext for that persistentContainer. 21
If any of that was confusing at all, 22
make sure that you have a look back at when we first wrote this line of code, and also the animations 23
where we walk through how this worked. 24
Now, the next thing is to setup our TableView Datasource Methods, 25
so we should know the required ones by now, 26
right? 27
It's table view numberOfRowsInSection and we're going to return, 28
of course, the number of items in our categories array. 29
So return categories.count. 30
All right. 31
So onto the next obligatory table view delegate method which is tableView cellForRowAt indexPath 32
which is here, cellForRowAt indexPath. 33
So here we are going to-- 34
So here we are going to dequeue a ReusableCell withIdentifier for indexPath. 35
So this creates a reusable cell and adds it to the table at the index path. 36
So the identifier is a string. And let's just go back and check what we called it and we called it 37
CategoryCell. 38
So I'm just gonna copy and paste it into here as the identifer and the index path is, of course, the current 39
indexPath that the table view is trying to load up. 40
Now, once we've created our reusable cell-- Now, once we've created our reusable cell, we got to set the 41
cell's textLabel.text property and we're gonna set it to equal categories at indexPath.row, 42
and we're going to tap into the category's name property or name attribute that we created earlier on. 43
That property gets automatically generated because we added it as an attribute. 44
And finally all that's left to do is to simply return the cell, and it will be rendered on screen. 45
Now, the next thing I'm going to work on is the addButtonPressed IBAction, and here we're going to 46
create a new alert which is going to be created from a UIAlertController and I'm gonna use the initializer 47
that takes a title which we'll call "Add New Category," message, we'll leave blank, and the preferred style 48
will just be alert. And then I'm going to create a action = UIAlertAction. 49
And this also takes a title which is going to be the word just "Add." That's gonna be the name of the button. 50
The style is just going to be default action and I'm going gonna select the placeholder for the handler 51
and hit enter so that it creates this completion handler for us. 52
I'm going to name the alert action just action. 53
We're not really going to use it. And I'm going to delete the code placeholder. 54
Now, inside this completion block or closure is where we're going to specify what should happen once 55
the user clicks that add button. 56
But before we do that, we're going to say alert.addAction and the action we want to add is the one 57
that we created just now. 58
And we're also going to setup our text field. So we do that using alert.addTextField, and we're 59
going to hit enter on the configuration handler, and we're going to call our text field just field. 60
And once that new text field has been created and added to the alert, we're going to store a reference to it 61
by creating a variable called textField which is going to be a new UITextField object, and then we're 62
going to set that textField to be equal to the field that is created inside our alert. And then we're 63
going to set the textfield's placeholder to maybe something like "Add a new category." 64
And finally, we're going to say present, view controller to present is the alert view controller, animated: 65
true, completion: nil. 66
Okay. 67
So, now it's time to address what should happen when the user clicks on the Add button inside the alert. 68
Well, this is where we have to create a new NSManagedObject and that is going to be a new category. 69
So let 70
newCategory = category. 71
Now, notice how this also a type alias called OpaquePointer that also has the name category. 72
So make sure you don't pick the OpaquePointer, pick our category instead, and also double-check the data 73
type by option clicking on category afterwards. 74
And we have to create our category by specifying a context. We've already created a reference to our 75
context at the top of our file. 76
So that's the one we're going to use. 77
And by the way, if when you option-click on your category and Xcode tells you it's a OpaquePointer data 78
type, just surround the word 'Category' with backticks like this, 79
and that should solve the problem. But because we're inside a closure, remember, we have to write 80
self.context in order to refer to that variable. Now, we're going to set up the new category, newCategory.name 81
is going to equal to the 82
textField.text 83
So whatever the user entered into that textField inside the alert is gonna be the name of the new category. 84
And then we're going to grab a reference to our array of category objects by saying 85
self.categories.append, 86
and we're going to add this newCategory to the array. 87
And finally, we're going to call saveCategories. 88
And this method, of course, doesn't exist which is why it's not being highlighted. 89
So this is a good time to go into our Data Manipulation Methods section over in the middle here and 90
add that function saveCategories. 91
And now Xcode reminds us that, of course, we need the "self" in front of saveCategories because we're 92
inside a closure, 93
and then it changes color to reflect the fact that it recognizes what we're talking about and which 94
method we want to use. 95
So inside our saveCategories method, I'm going to try and commit our context to our persistent container 96
by saying context.save. Now, because this throws, then I'm going to hold it inside a do catch block 97
and I'm going to log or print any errors that it catches, so "Error saving category" and the error is error. 98
All right. 99
And finally, once we have saved successfully, we're going to call tableView.reloadData so that our 100
table view updates with our latest data. 101
Now, the last thing that we have to do is we need to call a method called loadCategories 102
when we first initialize our CategoryViewController. and that also does not exist, 103
so we need to add that over here. I'm gonna create a function called loadCategories. 104
And inside here, we need to read data from our context. And to read data from our context, 105
we need to specify a request and we need to specify the data type of the request as a NSFetchRequest 106
that is going to return an array of category items. 107
And this is going to be equal to a broad request, 108
so we want to grab all of the category objects. 109
So we're going to say Category.fetchRequest, so we get back all the NSManagedObjects that were 110
created using the category entity. 111
So now we're going to say try context.fetch and we're going to fetch back all the results that fit 112
our current request. 113
And if our fetching of our requests succeeds, then we're going to save the output or whatever gets returned 114
from this method into our categories array. 115
So we can say categories = try context.fetch(request). And because this method can throw, then it's 116
a good idea to trap it inside a do catch block where we're going to print and say there was an 117
"Error loading categories" and this was the error code, an error message. So, now all we have left to do is we 118
have to tell the tableView to reload the data using our latest version of categories after fetching 119
all of the category object. 120
So let's give our app a go and see if all of that code works. 121
Cool. 122
So we're bringing up a blank table view because, currently, we still don't have any categories. And you 123
can confirm that if you go into the SQLite database. 124
But if we add some new categories, let's say, I don't know, Shopping List, maybe another one called Home, 125
and one called Work, and maybe one called Miscellaneous. 126
Okay. 127
So we now have four categories. And we can check to make sure that they are indeed being persisted using 128
Core Data by double tapping the home screen, terminating our app, and going back into our app. 129
And as you can see, they are still exactly where we left them. 130
So our code has succeeded. 131
So if you had any problems setting up your code up to this point, then it might be worth going back to 132
your code and seeing if there's any errors or bugs that you can fix. 133
Now, in the next lesson, we're going to set up our Table View Delegate Methods, namely, what should happen 134
when we click on one of the category cells, because when I click on home, I wanted to take me to a table 135
view that contains all of the to-do list items that are associated with the home category. 136
So for all of that and more, I'll see you on the next lesson.