0 1 00:00:00,880 --> 00:00:05,150 So in the last lesson, we manage to successfully implement our search bar, 1 2 00:00:05,230 --> 00:00:10,680 but now we want to be able to go back to our original list of all of our items. 2 3 00:00:10,690 --> 00:00:16,180 For example, when we click on the cross button, right? That's a normal behavior that users have gotten used to 3 4 00:00:16,270 --> 00:00:17,910 when they clear the search bar. 4 5 00:00:17,920 --> 00:00:23,440 So let's go into our TodoListViewController extension which is the part that deals with our search 5 6 00:00:23,440 --> 00:00:24,610 bar methods, 6 7 00:00:24,610 --> 00:00:28,280 and let's go and create a new delegate method here. 7 8 00:00:28,330 --> 00:00:32,080 And the method that we're going to use is, of course, relating to the search bar. 8 9 00:00:32,200 --> 00:00:39,540 And we're going to look for the delegate method that is searchBar textDidChange. 9 10 00:00:39,610 --> 00:00:45,390 So this triggers the delegate method when the text inside the searchBar has changed, 10 11 00:00:45,400 --> 00:00:52,480 so that means every single letter I type in here is going to trigger this delegate method. But also when 11 12 00:00:52,480 --> 00:00:59,160 I go from a whole bunch of text to no text, this delegate method is also going to be triggered. 12 13 00:00:59,170 --> 00:01:04,120 Now, I can isolate that particular instance by checking inside this delegate method. 13 14 00:01:04,120 --> 00:01:11,950 So whenever there are any changes inside the text of the searchBar, I can see if the 14 15 00:01:12,310 --> 00:01:20,440 searchBar.text.count which looks at the number of characters in the string or the searchBar text is equal 15 16 00:01:20,440 --> 00:01:21,540 to zero. 16 17 00:01:21,670 --> 00:01:28,810 And because of where this "if" statement exists, it means that text inside the search bar has changed, but 17 18 00:01:28,930 --> 00:01:31,890 it has also gone down to zero. 18 19 00:01:32,050 --> 00:01:40,210 So when we first load up the app and the search bar has no characters inside, this method, this delegate 19 20 00:01:40,210 --> 00:01:46,390 method is not going to trigger because the text has not changed, and it's only when the text is changed 20 21 00:01:46,870 --> 00:01:48,890 and it's gone down to zero 21 22 00:01:49,090 --> 00:01:53,050 which pretty much describes the time point when I click that cross button 22 23 00:01:53,050 --> 00:01:56,160 does this part of the code inside this "if" statement get triggered. 23 24 00:01:56,320 --> 00:02:04,240 So inside here, I'm simply going to call loadItems, which if you' remember, have a default request that 24 25 00:02:04,330 --> 00:02:08,160 just fetches all of the items from my persistent store, 25 26 00:02:08,290 --> 00:02:11,340 just as we had up here in the viewDidLoad. 26 27 00:02:11,380 --> 00:02:18,700 So, now if we run our app, and let's try and check it out, let's search for "Save," hit search, and then we're 27 28 00:02:18,700 --> 00:02:26,770 going to click the cross button, and you can see that we are now reverted to our original list of items. 28 29 00:02:26,770 --> 00:02:33,640 Now, this just one niggling thing. The fact that our keyboard has not dismissed itself and our cursor 29 30 00:02:33,640 --> 00:02:36,490 is still flashing in the search bar, 30 31 00:02:36,550 --> 00:02:42,550 now how can we get it to go back to the original state where the search bar doesn't have a cursor and 31 32 00:02:42,550 --> 00:02:44,220 the keyboard is dismissed? 32 33 00:02:44,230 --> 00:02:49,490 So, in order to do that, we need to call upon a method called resign first responder, 33 34 00:02:49,630 --> 00:02:54,710 so telling the search bar to stop being the first responder. 34 35 00:02:54,940 --> 00:03:00,580 Now, we're going to do it inside here after we call loadItems and we grab a reference to the 35 36 00:03:00,580 --> 00:03:01,870 searchBar that we've got, 36 37 00:03:02,020 --> 00:03:10,170 and we're saying resignFirstResponder which notifies this object, i.e., the searchBar that it has been 37 38 00:03:10,260 --> 00:03:15,000 asked to relinquish its status as the first responder in its window. 38 39 00:03:15,000 --> 00:03:16,660 Now, that sounds pretty dramatic, right? 39 40 00:03:16,680 --> 00:03:19,550 It's like, you know, you're being overthrown or something. 40 41 00:03:19,680 --> 00:03:25,810 But actually all it refers to is that it should no longer be the thing that is currently selected, 41 42 00:03:26,040 --> 00:03:32,040 so no longer have the cursor and also the keyboard should go away because we are no longer editing it 42 43 00:03:32,130 --> 00:03:32,690 anymore. 43 44 00:03:32,700 --> 00:03:38,190 Basically, go to the background, go to the original state you're in before you are activated. 44 45 00:03:38,190 --> 00:03:44,640 Now, whenever you're writing methods to affect the user interface, you tend to want it to tap in the 45 46 00:03:44,640 --> 00:03:45,630 foreground. 46 47 00:03:45,630 --> 00:03:52,470 Now, if we run the app and have an active session, if I click on the pause button here in the debug console, 47 48 00:03:53,220 --> 00:03:59,640 you can see that we can trigger a debug session. And it's at this point that you can see that we've got 48 49 00:03:59,640 --> 00:04:07,290 actually multiple threads that are running, but only one of them is the main thread in our queue. 49 50 00:04:07,380 --> 00:04:15,450 So for example, if I decided to make a network call to, say, a Firebase database on the main thread, then 50 51 00:04:15,450 --> 00:04:20,020 it means that it has to go over the Internet, grab the data back, 51 52 00:04:20,280 --> 00:04:26,620 and no matter how long that process takes, it's going to freeze your app until it completes 52 53 00:04:26,850 --> 00:04:33,000 which is why we tend to complete those tasks in the background using another thread which means the 53 54 00:04:33,180 --> 00:04:35,430 user interface is not going to freeze up 54 55 00:04:35,550 --> 00:04:41,340 while we're waiting for that process to complete. And on the background thread, once that process is complete, 55 56 00:04:41,700 --> 00:04:47,540 then the data gets delivered back and we can update the user interface using the main thread. 56 57 00:04:47,610 --> 00:04:53,790 But in our case, while background task are happening, we need to grab the main queue so that we can dismiss 57 58 00:04:53,830 --> 00:04:54,330 our searchBar, 58 59 00:04:54,340 --> 00:04:57,620 even if background tasks are still being completed. 59 60 00:04:57,750 --> 00:05:01,990 So in order to do that, we have to tap into the dispatchQueue 60 61 00:05:02,220 --> 00:05:07,040 and this is the object that manages the execution of work items. 61 62 00:05:07,260 --> 00:05:13,020 So it's almost like when you're submitting an application for a visa, right, to an embassy, and you have 62 63 00:05:13,020 --> 00:05:18,180 somebody at that embassy who is prioritizing who should be processing your visa. 63 64 00:05:18,180 --> 00:05:24,750 So, for example, if you were a diplomat or you paid for, you know, extra fast service, then your passport 64 65 00:05:24,810 --> 00:05:30,900 might get sent by the manager to the guy who's, you know, working 24/7 stamping visas, so that your visa 65 66 00:05:30,900 --> 00:05:33,250 processing happens immediately. 66 67 00:05:33,600 --> 00:05:39,660 However, if you are just, you know, just a standard person trying to get a visa to, you know, somewhere exotic 67 68 00:05:39,660 --> 00:05:45,320 for the winter, then you might get shuffled to, you know, the guy who only works one hour a day, 68 69 00:05:45,510 --> 00:05:50,700 and they have so many tasks lined up that it might take you a week before you get your visa processed, 69 70 00:05:50,700 --> 00:05:52,750 again, and get your passport back. 70 71 00:05:52,770 --> 00:05:58,660 So the DispatchQueue is that manager who assigns these projects to different threads. 71 72 00:05:58,980 --> 00:06:03,520 And we're going to ask it to grab us the main thread. 72 73 00:06:03,690 --> 00:06:08,050 And this is where you should be updating your user interface elements. 73 74 00:06:08,190 --> 00:06:11,250 And then we're going to tap into a async method. 74 75 00:06:11,490 --> 00:06:18,800 And inside this block of code, we're going to insert our searchBar updating code. 75 76 00:06:18,840 --> 00:06:23,640 So whenever you're trying to move code inside Xcode, it's a little bit tricky because it's a matter 76 77 00:06:23,640 --> 00:06:24,420 of timing. 77 78 00:06:24,600 --> 00:06:29,820 You have to click on it and wait for the arrow to appear and the cursor to disappear before you start 78 79 00:06:29,820 --> 00:06:30,430 dragging. 79 80 00:06:30,460 --> 00:06:31,780 Now, you can move your code. 80 81 00:06:32,010 --> 00:06:37,760 So now we're saying "Ask the DispatchQueue to get the main key, and then run this method on the main queue. 81 82 00:06:37,890 --> 00:06:45,420 So, now if I run my app and we hit search, then we get back all the items that has the word "Save." But when 82 83 00:06:45,420 --> 00:06:52,420 we dismiss the word "Save," then our keyboard pops away and our cursor disappears from our search bar. 83 84 00:06:52,590 --> 00:06:57,360 All because of this line of code being run in the foreground. 84 85 00:06:57,360 --> 00:07:02,220 Now, in the next lesson, we're going to take Core Data much further, and we're going to learn about one 85 86 00:07:02,220 --> 00:07:08,910 of its main features which is establishing relationships or what we might call graphs inside Core Data. 86 87 00:07:09,030 --> 00:07:13,950 And we're going to turn our simple to-do list into one that's more like a real-life to-do list 87 88 00:07:13,950 --> 00:07:18,180 by having a separate to-do list for various categories. 88 89 00:07:18,180 --> 00:07:20,940 So for all of that and more, I'll see you on the next lesson.