0 1 00:00:00,970 --> 00:00:06,850 So, now that we've learned about the different ways that we can use name parameters in Swift functions, 1 2 00:00:07,240 --> 00:00:13,600 let's go ahead and modify our delegate method didUpdateWeather to be more in line with the way that 2 3 00:00:13,720 --> 00:00:15,800 Apple formats their delegate methods. 3 4 00:00:16,270 --> 00:00:23,320 So you can see that the first thing that by convention, we always have in a delegate method is the identity 4 5 00:00:23,470 --> 00:00:26,820 of the object that caused this delegate method. 5 6 00:00:26,830 --> 00:00:31,990 So in their case, it's the text field which triggers the textFieldDidEndEditing. 6 7 00:00:32,170 --> 00:00:37,630 And in our case, it would actually be the weatherManager that does this. 7 8 00:00:37,630 --> 00:00:46,100 So this is, obviously, going to be of data type WeatherManager and we can now separate out our two 8 9 00:00:46,190 --> 00:00:47,460 parameters. 9 10 00:00:47,570 --> 00:00:51,500 Now, notice how they actually have an emitted parameter name here, 10 11 00:00:51,530 --> 00:00:57,980 so we can do the same. And we can add an underscore here and remember to separate the underscore from 11 12 00:00:57,980 --> 00:01:06,680 the internal parameter name. And we, of course, have to update this in the protocol that defines how our 12 13 00:01:06,680 --> 00:01:08,450 delegate methods are meant to look. 13 14 00:01:08,450 --> 00:01:10,220 So let's update that here as well. 14 15 00:01:10,910 --> 00:01:17,240 So, now when we actually call this didUpdateWeather, you can see that it's telling us that we're missing 15 16 00:01:17,270 --> 00:01:21,320 the parameter for the first input which is the WeatherManager. 16 17 00:01:22,190 --> 00:01:28,280 So the weather manager is going to be "self," this current object, which is the one that triggered 17 18 00:01:28,340 --> 00:01:34,130 the didUpdateWeather and it's also the one that knows all about the current weather conditions and passes over 18 19 00:01:34,220 --> 00:01:36,840 this weather object. 19 20 00:01:37,140 --> 00:01:42,810 So by using these omitted parameter names, we can actually clean up a lot of our method names and make 20 21 00:01:42,810 --> 00:01:45,800 them more succinct and easier to understand. 21 22 00:01:45,900 --> 00:01:52,590 For example, when we say parseJSON and we're passing in a piece of weatherData, now that's quite useful 22 23 00:01:52,590 --> 00:01:58,040 within the function, especially when we want to actually use it to decode, 23 24 00:01:58,140 --> 00:02:05,430 but from outside the function, this is a little bit extraneous self.parseJSON weatherData: 24 25 00:02:05,430 --> 00:02:06,360 safeData. 25 26 00:02:06,360 --> 00:02:13,890 I think it's entirely possible to omit that external argument and simply just have parseJSON with this 26 27 00:02:13,890 --> 00:02:22,370 particular data. And in other places, you'll see that Swift likes to use words from English that make 27 28 00:02:22,460 --> 00:02:28,850 the method names a lot more readable. For example, here where we've got performRequest (urlString: 28 29 00:02:28,850 --> 00:02:32,180 urlString) that feels a little bit extra as well. 29 30 00:02:32,540 --> 00:02:39,170 Instead, it would read a lot nicer and be more clear in English at least if we simply said performRequest 30 31 00:02:39,320 --> 00:02:41,140 with your urlString. 31 32 00:02:41,270 --> 00:02:46,360 So that method named now reads really nicely and when we call performRequest, 32 33 00:02:46,370 --> 00:02:51,980 we can say performRequest with: and then we pass in the urlString that we're going to perform the 33 34 00:02:51,980 --> 00:02:53,420 request with. 34 35 00:02:53,420 --> 00:02:59,660 These are all ways of making our code more readable, more easily understood by other programmers and 35 36 00:02:59,660 --> 00:03:02,690 also ourselves in the future. 36 37 00:03:02,690 --> 00:03:09,590 Now, with this in mind, I'm going to go ahead and add one other delegate method. And the delegate method 37 38 00:03:09,590 --> 00:03:14,540 is going to help us be able to pass errors out of our weather manager. 38 39 00:03:15,380 --> 00:03:22,730 I'm going to call the method didFailWithError and the input is going to be called error, and it's 39 40 00:03:22,730 --> 00:03:24,560 going to be of type Error. 40 41 00:03:25,790 --> 00:03:33,050 So, now we can trigger this delegate method whenever our code might fail in the WeatherManager, so that 41 42 00:03:33,050 --> 00:03:38,780 we can notify the delegate, "Hey, there's an issue here," so that we can pass this error out of our 42 43 00:03:38,780 --> 00:03:43,130 WeatherManager. And a good place to do that is, for example, here, 43 44 00:03:43,400 --> 00:03:50,570 if during our networking session, we somehow, say, lost connection to the internet, went underground, some 44 45 00:03:50,570 --> 00:03:54,160 sort of issue there, then we'd probably end up with an error. 45 46 00:03:54,500 --> 00:04:02,240 So instead of printing it here, we can pass it back to the delegate by saying delegate.didFailWithError, 46 47 00:04:02,330 --> 00:04:10,070 and pass in the error object that's unwrapped. And, of course, because we're inside a closure, 47 48 00:04:10,070 --> 00:04:14,330 we have to add the word "self" in front to complete that line of code. 48 49 00:04:14,390 --> 00:04:23,930 Now, down here inside where we parse our JSON, we can also possibly fail when our data can actually 49 50 00:04:23,930 --> 00:04:25,930 be decoded successfully. 50 51 00:04:26,030 --> 00:04:31,510 Say, maybe we had an issue with the way that we constructed our weatherData or maybe, in fact, we got 51 52 00:04:31,510 --> 00:04:35,090 a JSON that doesn't even match this format that we've created. 52 53 00:04:36,320 --> 00:04:43,940 So in that case, we're going to catch the error and we can, again, call our delegate.didFailWithError, 53 54 00:04:43,970 --> 00:04:52,130 and we can pass in the error that we've caught. So, now back over in the WeatherViewController, 54 55 00:04:52,310 --> 00:05:01,030 we, of course, must implement this method didFailWithError and we can handle any errors that occur 55 56 00:05:01,390 --> 00:05:02,950 while using the WeatherManager. 56 57 00:05:03,310 --> 00:05:10,270 So the simplest way is to, of course, simply just print the error. But depending on what kind of errors 57 58 00:05:10,270 --> 00:05:14,940 you might get, you might want to relay some of that back to the user. 58 59 00:05:14,980 --> 00:05:22,240 Now, in my case, because the errors that were getting are "couldn't parse JSON," or networking errors, I don't 59 60 00:05:22,240 --> 00:05:25,750 think the user is going to understand what that's all about. 60 61 00:05:25,780 --> 00:05:31,030 So in fact, all that we're going to do is we're just going to print the error to the console. And during 61 62 00:05:31,030 --> 00:05:36,880 the testing of our app, say, we could switch off the Wi-Fi, switch off the 3G Internet, and see if we get 62 63 00:05:36,880 --> 00:05:41,040 any errors that gets printed. In the next lesson, 63 64 00:05:41,080 --> 00:05:43,930 we're going to update the weather that's being shown on the screen.