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