0 1 00:00:00,270 --> 00:00:00,860 Hey, guys. 1 2 00:00:00,870 --> 00:00:06,960 So we've been talking a lot about the viewDidLoad or viewWillAppear, or viewDidDisappear which 2 3 00:00:06,960 --> 00:00:12,510 are some of the methods that you saw only just in the last lesson, but we haven't really learned much 3 4 00:00:12,570 --> 00:00:13,590 about these. 4 5 00:00:13,590 --> 00:00:20,790 So in this lesson, I want to talk about the lifecycle methods of a ViewController. And just as we humans 5 6 00:00:20,910 --> 00:00:23,380 are born and we eventually die, 6 7 00:00:23,430 --> 00:00:30,810 so do ViewControllers. And they have a lifecycle with certain key moments that we can tap into and 7 8 00:00:30,810 --> 00:00:36,200 we can write code to specify what should happen in those moments. 8 9 00:00:36,210 --> 00:00:40,730 The first thing that happens is the view gets loaded up. 9 10 00:00:40,740 --> 00:00:48,630 So in this case, all of the IBOutlets, IBActions, all of the view related objects gets connected up 10 11 00:00:48,840 --> 00:00:50,880 and is now accessible. 11 12 00:00:50,880 --> 00:00:57,870 Now, it's really important to note that the viewDidLoad method is only called once when the view is 12 13 00:00:57,870 --> 00:01:04,550 created, whereas the next method that we'll see in the lifecycle can get called many times. 13 14 00:01:04,590 --> 00:01:11,430 So after the view has been loaded up, then the next thing that the operating system will call is 14 15 00:01:11,670 --> 00:01:17,300 viewWillAppear, and this is called just before the view actually shows up on the screen. 15 16 00:01:17,430 --> 00:01:24,720 So the user is not yet able to see anything, but it is, however, a good time point for us to be able to 16 17 00:01:24,720 --> 00:01:32,550 hide or show certain UI components like what we did in our FlashChat app when we hid the navigation 17 18 00:01:32,550 --> 00:01:41,250 bar because the user is not yet able to detect any changes in the view, and it's only when the next step 18 19 00:01:41,250 --> 00:01:44,070 gets called which is viewDidAppear, 19 20 00:01:44,190 --> 00:01:47,490 are they able to actually see things on the screen. 20 21 00:01:47,670 --> 00:01:54,180 And at this point, if you tap into this method, then the view is already on screen and the user is already 21 22 00:01:54,180 --> 00:01:55,860 able to see the ViewController. 22 23 00:01:56,250 --> 00:02:02,670 So this is a good time point to, for example, start a countdown timer if you were going to do that on 23 24 00:02:02,670 --> 00:02:05,050 the screen or start an animation, 24 25 00:02:05,070 --> 00:02:10,560 anything that the user can detect, basically. Now after viewDidAppear, 25 26 00:02:10,560 --> 00:02:17,400 the user might do something to trigger the next method which is viewWillDisappear. 26 27 00:02:17,400 --> 00:02:23,280 Say, for example, if they navigate it back or if they somehow dismissed this current ViewController, then 27 28 00:02:23,280 --> 00:02:28,830 this is the first method that's going to be called to allow you to write some code to prepare for this 28 29 00:02:28,830 --> 00:02:29,550 event. 29 30 00:02:29,580 --> 00:02:34,920 So, for example, you probably want to stop your animations and you might want to change the appearance 30 31 00:02:34,920 --> 00:02:35,710 of UI, 31 32 00:02:35,730 --> 00:02:39,930 say, for example, like when we hid our navigation bar. 32 33 00:02:39,930 --> 00:02:44,820 Now, the step after viewWillDisappear is, of course, viewDidDisappear, 33 34 00:02:44,820 --> 00:02:48,030 and at this point, the view is already off the screen 34 35 00:02:48,030 --> 00:02:54,150 and this is, basically, the last moment where we get to change anything about that previous view before 35 36 00:02:54,240 --> 00:02:56,470 it disappears off the screen. 36 37 00:02:56,490 --> 00:03:03,090 Now, just because the view has disappeared, it doesn't mean that it has been deallocated or has been 37 38 00:03:03,360 --> 00:03:10,860 deleted from the memory of the phone. And in fact, as you'll see in the next demonstration viewDidDisappear, 38 39 00:03:10,890 --> 00:03:15,030 literally, just means that the user can't see it. 39 40 00:03:15,030 --> 00:03:20,340 It doesn't say anything about whether if the ViewController is going to be destroyed or if it's just 40 41 00:03:20,340 --> 00:03:24,360 going to be kept in the background in the navigation stack. 41 42 00:03:24,360 --> 00:03:31,290 So I've created a really simple example where I've added all of these possible methods that we can override 42 43 00:03:31,710 --> 00:03:38,370 from viewDidLoad to viewDidDisappear, and I've added a print statement in each of them to show you 43 44 00:03:38,370 --> 00:03:39,800 when they get called. 44 45 00:03:40,110 --> 00:03:47,150 And I've linked up a second ViewController which basically has the same code all of those lifecycle 45 46 00:03:47,160 --> 00:03:47,970 methods. 46 47 00:03:47,970 --> 00:03:51,760 But instead, it says, "VC2 viewDidLoadCalled." 47 48 00:03:51,780 --> 00:03:58,720 So this allows us to have a realtime view as to which of these methods are being called when. 48 49 00:03:58,740 --> 00:04:03,900 Now, if we take a quick look at the Main.storyboard, you can see that it's a really simple interface, 49 50 00:04:03,960 --> 00:04:06,040 it's just got two ViewControllers: 50 51 00:04:06,060 --> 00:04:08,530 ViewController1 and ViewController2. 51 52 00:04:08,760 --> 00:04:14,450 And the first one has a button which has a segue that navigates the second one. 52 53 00:04:14,670 --> 00:04:21,510 And on the second screen, I've got Back button, which then calls the dismiss method which allows us 53 54 00:04:21,510 --> 00:04:29,280 to go back to ViewController1, and it will destroy and dismiss this second ViewController. 54 55 00:04:29,280 --> 00:04:36,400 So let's go ahead and run our app and see what's being called when. 55 56 00:04:36,430 --> 00:04:41,090 Now, let me just go ahead and expand this area, so you can see the order of things. 56 57 00:04:41,140 --> 00:04:47,620 The first thing that happens is on VC1, viewDidLoad gets called, and then viewWillAppear, and 57 58 00:04:47,620 --> 00:04:48,670 then viewDidAppear. 58 59 00:04:49,210 --> 00:04:54,040 Now, it's going to hold still until the user performs some sort of action. 59 60 00:04:54,070 --> 00:05:00,710 So for example, I might click on the next button which is going to take me to the second ViewController. 60 61 00:05:00,730 --> 00:05:06,970 Now, in this case, the ViewController2 gets loaded up, and then viewWillAppear, and viewDidAppear 61 62 00:05:07,000 --> 00:05:08,440 gets called. 62 63 00:05:08,440 --> 00:05:15,910 And finally, when I click on back, what will happen is that the viewWillDisappear and viewDidDisappear 63 64 00:05:16,080 --> 00:05:19,440 will get called from the second ViewController. 64 65 00:05:19,450 --> 00:05:26,980 Now, you might be wondering, well, why is viewDidDisappear or viewWillDisappear not being called from 65 66 00:05:27,030 --> 00:05:28,660 VC1? 66 67 00:05:28,690 --> 00:05:35,800 Well, it's because when we navigate over, the segue is set up in such a way that our ViewControllers are 67 68 00:05:35,800 --> 00:05:38,680 displayed like cards one on top of each other. 68 69 00:05:39,190 --> 00:05:45,100 So, in fact, that previous ViewController hasn't really disappeared, 69 70 00:05:45,100 --> 00:05:45,870 right? 70 71 00:05:45,970 --> 00:05:54,280 And all it's doing is just hiding there in the background and it hasn't fully disappeared. 71 72 00:05:54,280 --> 00:06:02,530 Now, you'll notice that as soon as I click on the second ViewController and start pulling it down, 72 73 00:06:02,530 --> 00:06:09,790 ViewControllerWillDisappear gets called in preparation for the event where ViewController2 is going 73 74 00:06:09,790 --> 00:06:11,160 to disappear. 74 75 00:06:11,470 --> 00:06:19,600 But if I was to go here and I was to change the segue, so from the default Show to Present Modally, 75 76 00:06:19,960 --> 00:06:26,830 and then change the Presentation type to Full Screen, so that the second view completely covers the previous 76 77 00:06:26,830 --> 00:06:32,560 view, and that ViewController1 actually does, in fact, disappear from the phone. 77 78 00:06:32,560 --> 00:06:34,390 So let's run this as it is now. 78 79 00:06:37,190 --> 00:06:38,790 And, again, we get viewDidLoad, 79 80 00:06:38,830 --> 00:06:40,460 viewWillAppear, viewDidAppear. 80 81 00:06:40,670 --> 00:06:47,650 But now notice how once the second view controller is fully covering the previous view controller, 81 82 00:06:47,660 --> 00:06:54,290 we're getting viewWillDisappear being called and, eventually, the VC1 viewDidDisappear 82 83 00:06:54,310 --> 00:06:57,830 gets called once it can no longer be seen. 83 84 00:06:57,830 --> 00:07:04,220 Notice how if I keep going back and forth between these two view controllers, were getting this VC1 84 85 00:07:04,220 --> 00:07:08,820 viewWillAppear and viewDidAppear being called many times, 85 86 00:07:08,840 --> 00:07:09,590 right? 86 87 00:07:09,710 --> 00:07:15,800 And that's because it does appear and disappear quite a few times, but you'll notice that the viewDidLoad 87 88 00:07:15,800 --> 00:07:22,380 for VC1 only gets called once and that's the first time it gets loaded up, 88 89 00:07:22,460 --> 00:07:25,610 and that's because it's always living there in the background. 89 90 00:07:25,610 --> 00:07:26,830 It's not getting destroyed. 90 91 00:07:26,870 --> 00:07:28,880 It's just being covered. 91 92 00:07:28,880 --> 00:07:35,360 Whereas when I click back on the second view controller, it is, in fact, getting destroyed and it is disappearing 92 93 00:07:35,360 --> 00:07:39,600 for good, instead of just hiding out somewhere. 93 94 00:07:39,620 --> 00:07:45,070 Now, this brings us to an interesting point and a really common source of confusion. 94 95 00:07:45,080 --> 00:07:53,120 Say, for example, because we have this segue that goes between the next button on VC1 over to VC2 95 96 00:07:53,150 --> 00:08:00,800 if I was to go into ViewController1 and add a prepare for segue method, then this is going to 96 97 00:08:00,800 --> 00:08:03,440 get triggered as soon as that segue happens. 97 98 00:08:03,440 --> 00:08:11,880 So let's create a destination VC from the segue.destination property, and we're going to downcast 98 99 00:08:11,880 --> 00:08:14,570 that as a ViewController2. 99 100 00:08:14,690 --> 00:08:21,170 Now, if this is at all confusing, just be sure to take a look back at the previous lessons where we covered 100 101 00:08:21,230 --> 00:08:25,220 the segues and down casting in more detail. 101 102 00:08:25,220 --> 00:08:30,860 So, now that I've got hold of a reference to the destination ViewController which is basically going 102 103 00:08:30,860 --> 00:08:38,870 to be a ViewController2 type, notice how here I've got an IBOutlet that's linked to a UILabel and 103 104 00:08:38,870 --> 00:08:41,630 that corresponds to this label right here. 104 105 00:08:42,140 --> 00:08:50,540 Well, what if I wanted to prepare for segue by tapping into this destinationVC and setting its label 105 106 00:08:51,620 --> 00:08:54,430 to have a text of "Hello." 106 107 00:08:55,280 --> 00:09:01,400 So let's go ahead and run this code and only if you can predict what happens. 107 108 00:09:01,400 --> 00:09:05,220 So we've got our standard viewDidLload, viewWillAppear, 108 109 00:09:05,210 --> 00:09:12,170 viewDidAppear being called, and now as soon as I click Next, it triggers the segue, and it should if 109 110 00:09:12,230 --> 00:09:20,570 our code was working. It should try to set that destinationVC's label. And you can see right here that 110 111 00:09:20,570 --> 00:09:30,560 this destinationVC is a ViewController2 data type, and it is a living breathing object. But at this 111 112 00:09:30,560 --> 00:09:38,860 point in time that UILabel has still not been created and nor has it been linked up to the ViewController, 112 113 00:09:38,870 --> 00:09:47,120 so if I try to run this code, I actually get a fatal error and a crash, and it's because it found nil 113 114 00:09:47,360 --> 00:09:51,140 when it was trying to access that label. 114 115 00:09:51,140 --> 00:09:59,090 This is why the viewDidLoad method is really, really useful, and we use it so much in our iOS development. 115 116 00:09:59,530 --> 00:10:06,620 It's because this time point inside these curly brackets, if you decide to write some code that's related 116 117 00:10:06,620 --> 00:10:14,030 to the view, say, a label or a button, or anything that's on screen, you are guaranteed that it has already 117 118 00:10:14,030 --> 00:10:16,070 been set up and created. 118 119 00:10:16,250 --> 00:10:23,030 If you were to write label.text = "hello," then you are guaranteed that this will not fail, 119 120 00:10:23,060 --> 00:10:29,240 because at this time point, the view has already loaded up, and that means that label is available for 120 121 00:10:29,240 --> 00:10:37,440 you to change. So I've included this project as a GitHub repository in the course resources page. 121 122 00:10:37,710 --> 00:10:43,610 So if you wanted to download it and have a play around with it, then feel free to do so. 122 123 00:10:43,620 --> 00:10:47,520 Alternatively, you can also just create these methods yourself. 123 124 00:10:47,550 --> 00:10:52,410 It doesn't take too long. But if you want to save yourself a bit of time, it's also there for you as well.