0 1 00:00:01,050 --> 00:00:07,440 In the last few lessons, we wrote our networking code to fetch the Weather Data and pass the JSON response 1 2 00:00:07,740 --> 00:00:09,320 from OpenWeather Map. 2 3 00:00:09,330 --> 00:00:13,400 Then we created our weather model to hold on to our weather data. 3 4 00:00:13,470 --> 00:00:18,600 In this lesson, we're going to tie it all together by writing the code to parse the weather information 4 5 00:00:18,870 --> 00:00:22,320 back to the Weather View Controller. And to do that, 5 6 00:00:22,350 --> 00:00:25,050 we're going to use delegates and protocols. 6 7 00:00:25,050 --> 00:00:31,170 Speaking of protocols, sometimes more than one protocol can be combined under a single name. 7 8 00:00:31,170 --> 00:00:34,770 Now, notice how we're using the Decodable protocol here. 8 9 00:00:34,770 --> 00:00:41,520 If you needed to be able to encode data back into JSON format, then you could also tag on another 9 10 00:00:41,520 --> 00:00:51,060 protocol which is the Encodable protocol which allows your Swift objects to be encoded into a JSON. 10 11 00:00:51,660 --> 00:00:54,590 Now, in order to save people time, 11 12 00:00:54,600 --> 00:01:00,280 they actually managed to create something called a Typealias that combines these two protocols, 12 13 00:01:00,450 --> 00:01:02,250 and it's called Codable. 13 14 00:01:02,490 --> 00:01:08,490 So when you see code out in the while that have this thing Codable that's added at the end, when you 14 15 00:01:08,490 --> 00:01:11,070 click on it, you see that "Oh, it's a typealias." 15 16 00:01:11,070 --> 00:01:12,060 What does that mean? 16 17 00:01:12,060 --> 00:01:19,620 Well, all it is is it just combines two protocols into one and we can add them both in one go. 17 18 00:01:19,620 --> 00:01:26,880 So that's something to be aware of. Now coming back to our parse JSON method, 18 19 00:01:27,130 --> 00:01:34,660 once we've created our weather object from our Weather model, I want to be able to return it to the place 19 20 00:01:34,720 --> 00:01:43,820 where I code parseJSON, so that way I could, for example, say, let weather = self.parseJSON. 20 21 00:01:43,840 --> 00:01:50,320 And to do this, I, of course, have to provide an output to this method and it is going to be the WeatherModel 21 22 00:01:50,380 --> 00:01:55,340 data type because that's what our weather is created from. 22 23 00:01:55,510 --> 00:01:57,160 So how do I output this? 23 24 00:01:57,160 --> 00:02:05,080 Well, I could simply just return weather right here that I've created from the data that I've parsed. 24 25 00:02:05,080 --> 00:02:10,270 But what if the parsing didn't go according to plan? 25 26 00:02:10,330 --> 00:02:13,740 What if we ended up with a error? 26 27 00:02:13,750 --> 00:02:17,320 What if this decoding process failed? 27 28 00:02:17,320 --> 00:02:22,690 Well in that case, it would actually skip all of these lines of code, and go straight to the catch block 28 29 00:02:22,750 --> 00:02:24,760 and print our error. 29 30 00:02:24,760 --> 00:02:32,350 Well, at this point, then we're not gonna get anything returned and our output is no longer being provided. 30 31 00:02:32,350 --> 00:02:38,000 So that's why we're getting this error: Missing return in a function expected to return "Weather Model." 31 32 00:02:38,020 --> 00:02:38,950 So what could we do? 32 33 00:02:39,160 --> 00:02:47,440 Well, we could in the catch instance, simply return nil because we don't actually have a weather object 33 34 00:02:47,440 --> 00:02:48,340 to return. 34 35 00:02:48,430 --> 00:02:54,430 We didn't manage to successfully decode the data. But in order for us to be able to set something as 35 36 00:02:54,430 --> 00:02:55,240 nil, 36 37 00:02:55,240 --> 00:02:58,790 well, then our WeatherModel has to become an optional. 37 38 00:02:58,810 --> 00:03:06,070 So, now we have this optional coming out of our parseJSON method and this is now an optional 38 39 00:03:06,070 --> 00:03:06,450 WeatherModel. 39 40 00:03:06,970 --> 00:03:14,710 But, of course, we want to be able to use it, so we can simply optional bind the weather object that comes 40 41 00:03:14,830 --> 00:03:20,320 out of parseJSON as the output to something called weather. 41 42 00:03:20,350 --> 00:03:27,820 Now, we can use this weather which is an unwrapped weather model object. What do we want to do with this 42 43 00:03:27,910 --> 00:03:29,080 weather object? 43 44 00:03:29,350 --> 00:03:34,570 Well, we want to send it back to the place where we need it which is the WeatherViewController. 44 45 00:03:34,690 --> 00:03:38,290 We want to use the condition name to populate the conditionImageView. 45 46 00:03:38,290 --> 00:03:41,800 We want to be able to just put the temperature into the temperatureLabel. 46 47 00:03:41,800 --> 00:03:48,710 So how do we get it back into the WeatherViewController? Well, one way that we could do this is to create 47 48 00:03:48,800 --> 00:03:50,110 a 48 49 00:03:50,160 --> 00:03:57,380 weatherViewControl object from our WeatherViewController, and then inside our WeatherViewController, 49 50 00:03:57,380 --> 00:04:05,120 we could create a function called didUpdateWeather and we would be able to pass in the WeatherModel object 50 51 00:04:05,210 --> 00:04:06,680 as the weather. 51 52 00:04:06,800 --> 00:04:13,910 And then inside here, we should be able to then print weather.temperature, and then going back to 52 53 00:04:13,910 --> 00:04:24,050 our WeatherManager, then we would call weatherVC.didUpdateWeather, and then we would be able 53 54 00:04:24,050 --> 00:04:27,920 to pass in this weather object as the input. 54 55 00:04:27,920 --> 00:04:36,290 Now, that would work, but if we come back to what we learn in our delegates and protocols lessons, by doing 55 56 00:04:36,290 --> 00:04:43,280 this, we would basically render our WeatherManager single use. It would become like a plastic cup or 56 57 00:04:43,280 --> 00:04:44,750 a plastic tray. 57 58 00:04:44,750 --> 00:04:50,690 We have to limit its use to this current project. But in a future project, if we needed to get weather 58 59 00:04:50,690 --> 00:04:59,150 data, well, we could reuse this struct WeatherManager. And the way that we would do that is by not using 59 60 00:04:59,270 --> 00:05:04,040 any specific code in it that ties it to another object, 60 61 00:05:04,040 --> 00:05:10,760 say, the WeatherViewController. So we could solve this problem by simply using a delegate pattern. 61 62 00:05:10,940 --> 00:05:15,470 We could say something like delegate if it exists, 62 63 00:05:15,470 --> 00:05:24,620 call didUpdateWeather, and inside the didUpdateWeather, we would maybe have a input code 63 64 00:05:25,080 --> 00:05:31,570 weather. And then, here we could pass in this weather object that we got back from our parseJSON. 64 65 00:05:31,580 --> 00:05:37,070 So here's my challenge to you. 65 66 00:05:37,070 --> 00:05:43,910 I want you to write this line of code exactly where you see it here inside the "if let" that unwraps the 66 67 00:05:43,910 --> 00:05:49,580 weather object that we get back from parseJSON. And we're going to try and parse this weather object 67 68 00:05:49,880 --> 00:05:55,820 back to the delegate. And the delegate is going to be our WeatherViewController. 68 69 00:05:55,820 --> 00:06:01,640 So that's going to be the class where we're going to trigger this method didUpdateWeather, but we're 69 70 00:06:01,640 --> 00:06:04,940 going to do it using the delegate design pattern. 70 71 00:06:04,940 --> 00:06:11,870 That means that in our WeatherManager, we wouldn't need a variable code delegate, and this should have 71 72 00:06:11,870 --> 00:06:15,220 the data type of WeatherManagerDelegate 72 73 00:06:15,470 --> 00:06:23,000 and it will be an optional, so that whoever or whichever class or struct sets themselves as 73 74 00:06:23,000 --> 00:06:28,670 the WeatherManagerDelegate would have to have the implementation for this method didUpdateWeather, 74 75 00:06:29,150 --> 00:06:35,660 so that we can actually call delegate?. didUpdateWeather and pass over the weather that we have in our 75 76 00:06:35,660 --> 00:06:36,500 WeatherManager 76 77 00:06:36,950 --> 00:06:43,460 and it should be able to land in our WeatherViewController, and we should be able to print out the 77 78 00:06:43,520 --> 00:06:46,740 temperature property of the weather. 78 79 00:06:47,150 --> 00:06:52,910 Pause the video now and see if you can complete this challenge that tests your knowledge of delegates 79 80 00:06:53,000 --> 00:06:57,160 and protocols. 80 81 00:06:57,280 --> 00:06:57,540 All right. 81 82 00:06:57,550 --> 00:07:01,190 The first thing we need to do is to create our protocol. 82 83 00:07:01,330 --> 00:07:04,180 So right up here outside of the WeatherManager, 83 84 00:07:04,390 --> 00:07:11,320 and remember that by convention in Swift, we create the protocol in the same file as the class that will 84 85 00:07:11,320 --> 00:07:13,720 use the protocol. 85 86 00:07:13,720 --> 00:07:19,320 In this case, the protocol is going to be called 86 87 00:07:19,390 --> 00:07:19,990 a WeatherManagerDelegate. 87 88 00:07:20,830 --> 00:07:23,550 So this is the name that we specified earlier. 88 89 00:07:23,800 --> 00:07:30,340 And then the requirements are that you must be able to implement a function code didUpdateWeather. 89 90 00:07:31,630 --> 00:07:34,650 And the inputs are called weather 90 91 00:07:34,690 --> 00:07:37,870 and it has to be of type WeatherModel. 91 92 00:07:37,870 --> 00:07:40,760 These are our requirements set out. 92 93 00:07:40,780 --> 00:07:46,360 So, now we set our delegate as a optional WeatherManagerDelegate, 93 94 00:07:46,360 --> 00:07:52,510 so if some class or some struct has set themselves as the delegate, then we would be able to call upon 94 95 00:07:52,510 --> 00:07:56,310 the delegate and tell it to update the weather. 95 96 00:07:56,350 --> 00:08:02,500 Now, remember that because we're inside a closure, our delegate has to have the keyword "self" in front 96 97 00:08:02,800 --> 00:08:09,430 to make it clear that referring to the delegate in the current class which is this one right here. 97 98 00:08:09,460 --> 00:08:17,950 So, now we have to go into our WeatherViewController and adopt that WeatherManagerDelegate. And as 98 99 00:08:17,950 --> 00:08:23,650 soon as we do that--right now, we're not actually getting errors because we already have implemented the 99 100 00:08:23,650 --> 00:08:30,420 method which is called didUpdateWeather because this is the requirement of that protocol. 100 101 00:08:30,550 --> 00:08:37,000 So adopting it, we have to have this. But because it already exists, we don't get any errors. 101 102 00:08:37,000 --> 00:08:45,970 But what we do have to do, which I often forget, is we do have to set this current class as the delegate. 102 103 00:08:45,970 --> 00:08:56,810 So we have to say that the WeatherManager.delegate property is equal to "self." That way, 103 104 00:08:56,820 --> 00:09:04,800 our WeatherManager's delegate property is not nil. And then, down here where we call delegate.didUpdateWeather, 104 105 00:09:05,130 --> 00:09:11,370 this optional chaining here will actually pass through because it's not nil, and then we actually trigger 105 106 00:09:11,400 --> 00:09:15,580 this didUpdateWeather and pass over this weather object. 106 107 00:09:15,810 --> 00:09:24,740 So let's give it a spin to see if it works. So, now let's search for the weather in Paris again, and you can 107 108 00:09:24,740 --> 00:09:27,820 see that we're getting the temperature sent over. 108 109 00:09:27,920 --> 00:09:28,540 Perfect. 109 110 00:09:28,550 --> 00:09:36,200 We're now adopting the delegate design pattern and our WeatherManager is now completely reusable. 110 111 00:09:36,320 --> 00:09:42,050 We could use this in any other class without having to change any of the code inside and all we would 111 112 00:09:42,050 --> 00:09:47,870 have to do is whatever class that needs this functionality of getting the weather data from OpenWeather Map, 112 113 00:09:47,870 --> 00:09:52,380 then we would simply adopt the WeatherManagerDelegate, 113 114 00:09:52,430 --> 00:09:59,510 set the class as the delegate, and then have the implementation of didUpdateWeather to be notified 114 115 00:09:59,720 --> 00:10:02,330 when the weather is available from the internet. 115 116 00:10:03,850 --> 00:10:08,680 This is a good time to mention that there's a couple of conventions that we use when we're adopting 116 117 00:10:08,680 --> 00:10:11,620 the delegate pattern like this in Swift. 117 118 00:10:11,620 --> 00:10:17,110 Notice how in the delegate methods that Apple has created, the way that they're written, they start out 118 119 00:10:17,110 --> 00:10:24,850 with an underscore, and then the parameter name, and then the data type. So why is it that there's an underscore 119 120 00:10:24,850 --> 00:10:29,050 there and why is it separated from the name of the tax field? 120 121 00:10:29,080 --> 00:10:35,050 This is because in Swift, we can have something called a local parameter name and we can even omit the 121 122 00:10:35,050 --> 00:10:38,590 parameter name when we're calling the method. To find out more about this, 122 123 00:10:38,590 --> 00:10:40,110 you can head over to the next lesson 123 124 00:10:40,160 --> 00:10:44,720 where we're going to do a Deep Dive on parameter names for Swift methods. 124 125 00:10:45,100 --> 00:10:50,200 If you already know all about this, then feel free to skip the next lesson where we continue building 125 126 00:10:50,200 --> 00:10:53,710 out our project and formatting our delegate methods.