0 1 00:00:00,630 --> 00:00:01,120 All right. 1 2 00:00:01,150 --> 00:00:08,500 So now that our app is actually pretty much fully functional, other than the fact that we still don't 2 3 00:00:08,500 --> 00:00:14,450 have the location data and we can't get the weather for the current location. 3 4 00:00:14,590 --> 00:00:17,920 So that's what we're going to tackle in this lesson. 4 5 00:00:18,350 --> 00:00:25,970 Now, the first thing we need to do to be able to get hold of the location data is to import a package 5 6 00:00:26,030 --> 00:00:29,990 that Apple has created called CoreLocation. 6 7 00:00:29,990 --> 00:00:34,190 And this comes with something called a location manager. 7 8 00:00:34,370 --> 00:00:43,290 So we can create a locationManager here and it's going to be created from 8 9 00:00:43,380 --> 00:00:44,510 the CLLocationManager class. 9 10 00:00:45,510 --> 00:00:51,390 And this object that we've created, our locationManager is going to be responsible for getting hold 10 11 00:00:51,480 --> 00:00:54,510 of the current GPS location of the phone. 11 12 00:00:55,200 --> 00:01:03,130 But before we can use it though, the first thing we have to do is we have to trigger a permission request. 12 13 00:01:03,270 --> 00:01:12,990 So we're going to say requestWhenInUseAuthorization. Because the user's location is a really private 13 14 00:01:12,990 --> 00:01:14,250 piece of data, 14 15 00:01:14,250 --> 00:01:21,660 you don't want apps to just know exactly where you are without having to ask for explicit permission. 15 16 00:01:21,660 --> 00:01:27,130 So when we call this locationManager.requestWhenInuseAuthorization method, 16 17 00:01:27,210 --> 00:01:28,420 wow, what a mouthful, 17 18 00:01:28,530 --> 00:01:34,640 then it will show a pop up on screen that asks the user for permission. 18 19 00:01:34,830 --> 00:01:41,580 But in addition to calling this method, we also have to go into the info.plist, which is the property 19 20 00:01:41,580 --> 00:01:49,860 list where we've got a bunch of key-value pairs that determine some of the basic settings of our app. 20 21 00:01:49,860 --> 00:01:54,350 And here, we're going to add a new property. 21 22 00:01:54,540 --> 00:02:01,380 And if you scroll down in this list, you should be able to find one that says, "Privacy - Location When in 22 23 00:02:01,380 --> 00:02:05,310 Use Usage Description. 23 24 00:02:05,560 --> 00:02:10,930 And for this key, we're going to give a value that's going to be the message that we're going to tell 24 25 00:02:10,930 --> 00:02:13,660 the user why we need their location. 25 26 00:02:13,660 --> 00:02:23,570 So, we'll say, "We need your location to get the current weather for where you are." 26 27 00:02:24,940 --> 00:02:32,500 So, now that we've got a Privacy - Location When in Use Usage Description, we can now head back and run our 27 28 00:02:32,500 --> 00:02:32,890 app. 28 29 00:02:35,940 --> 00:02:42,150 And as soon as the WeatherViewController loads up, you should see a pop up which is in black 29 30 00:02:42,150 --> 00:02:48,870 if you're in dark mode, like I am, or in white if you are not in dark mode. And it'll ask you, "Do you want 30 31 00:02:48,870 --> 00:02:51,990 to allow 'Clima' to access your location?" 31 32 00:02:51,990 --> 00:02:56,100 And then here is that little string that we added earlier on in our plist, 32 33 00:02:56,100 --> 00:02:58,990 "We need your location to get the current weather for where you are." 33 34 00:02:59,550 --> 00:03:04,350 So make sure that while you're testing, you always click on Allow because, otherwise, you're going to have 34 35 00:03:04,350 --> 00:03:11,790 to dig into the settings, the privacy and location settings, to allow the Clima app to access the location. 35 36 00:03:11,790 --> 00:03:18,540 So now that we've gotten permission from the user to get their location, well, then the next step is to 36 37 00:03:18,540 --> 00:03:27,440 use the locationManager to request location, and this method "Request for a one-time delivery of the 37 38 00:03:27,440 --> 00:03:29,090 user's current location." 38 39 00:03:29,370 --> 00:03:34,860 And because we're building a weather app here where we don't need to track where the user is or where 39 40 00:03:34,860 --> 00:03:36,000 their car is, 40 41 00:03:36,060 --> 00:03:43,890 so if you were building a navigation app or a fitness app where you needed the turn by turn location 41 42 00:03:43,890 --> 00:03:51,090 data the entire time that they're using the app, then you might want to use something called 42 43 00:03:51,120 --> 00:03:52,790 startUpdatingLocation instead 43 44 00:03:52,860 --> 00:03:59,760 and this basically monitors their location and constantly reports back when it updates. But in our case, 44 45 00:03:59,820 --> 00:04:03,420 the request location is sufficient. 45 46 00:04:03,420 --> 00:04:08,740 But how do we actually get hold of that location once the location manager has found it? 46 47 00:04:08,760 --> 00:04:12,780 Well, notice how requests location doesn't return anything. 47 48 00:04:12,780 --> 00:04:19,780 In fact, the only way to get a hold of it is through the locationManager(_:didUpdateLocations:) method. 48 49 00:04:19,920 --> 00:04:27,660 And this is what the locationManager is going to call once it finds the location. So given now that 49 50 00:04:27,660 --> 00:04:33,390 you know what the delegate method is that you need to implement and you know all about protocols and 50 51 00:04:33,390 --> 00:04:36,350 delegates, here's a challenge for you. 51 52 00:04:36,480 --> 00:04:44,970 See if you can implement the required protocols and simply be able to print got location when the 52 53 00:04:44,970 --> 00:04:48,300 locationManager triggers the didUpdateLocationsDelegate 53 54 00:04:48,360 --> 00:04:56,280 method. Also, try to use a Swift extension to split out the didUpdateLocation method from 54 55 00:04:56,280 --> 00:04:57,910 the WeatherViewController. 55 56 00:04:57,960 --> 00:05:03,120 Now, printing out got location can actually be a little bit harder than it sounds. 56 57 00:05:03,120 --> 00:05:08,190 Make sure you have a read of the documentation to figure out how to do this successfully. 57 58 00:05:08,190 --> 00:05:11,570 So pause the video and see if you can complete this challenge. 58 59 00:05:16,610 --> 00:05:16,910 All right. 59 60 00:05:16,940 --> 00:05:24,020 So firstly, we know that this method, once it gets hold of the location, is going to trigger this delegate 60 61 00:05:24,080 --> 00:05:25,160 method. 61 62 00:05:25,160 --> 00:05:33,680 And this delegate method if we click on it, shows us that it comes from the protocol 62 63 00:05:33,710 --> 00:05:34,580 CLLocationManagerDelegate. 63 64 00:05:34,780 --> 00:05:42,350 So we have to adopt this delegate protocol in our WeatherViewController if we want to be able to assign 64 65 00:05:42,350 --> 00:05:48,920 ourselves as the delegate for the locationManager to be notified of that location update. 65 66 00:05:48,920 --> 00:05:58,070 So we can either add our CLLocationManagerDelegate here, alternatively, as we saw in the last lesson. 66 67 00:05:58,370 --> 00:06:06,020 We could simply create a brand-new extension down here which extends our WeatherViewController. 67 68 00:06:06,590 --> 00:06:15,020 And here, we can add our CLLocationManagerDelegate, so that we split out this part of the functionality 68 69 00:06:15,140 --> 00:06:23,390 of our WeatherViewController and we can mark it out with MARK comment, and we can call this 69 70 00:06:23,750 --> 00:06:26,170 the 70 71 00:06:26,360 --> 00:06:27,170 CLLocationManagerDelegate. 71 72 00:06:27,170 --> 00:06:34,640 So you'll often see that people will split out their view controllers with sections that are named based 72 73 00:06:34,670 --> 00:06:38,410 on the delegate protocols that they are adopting. 73 74 00:06:38,420 --> 00:06:47,540 So this action is obviously related to the location manager, and the delegate method was called 74 75 00:06:47,660 --> 00:06:51,860 didUpdateLocations, location manager did update locations. 75 76 00:06:51,860 --> 00:06:56,040 So if we hit enter, that should enter that method for us. 76 77 00:06:56,090 --> 00:07:03,170 Now, you have to remember that in order to actually get the notification for this, we have to set our 77 78 00:07:03,170 --> 00:07:04,490 WeatherViewController, 78 79 00:07:04,520 --> 00:07:11,990 so this current class, as the delegate for the locationManager. Without this property set, nothing is 79 80 00:07:11,990 --> 00:07:16,760 going to happen even if you adopt the protocols and have the delegate methods. 80 81 00:07:16,760 --> 00:07:25,460 So, now that everything is all set, we can simply print "Got location data" and then go ahead and hit run. 81 82 00:07:29,230 --> 00:07:31,930 And at this point, your app will crash. 82 83 00:07:31,930 --> 00:07:37,660 And if you scroll right to the top, you'll see that you have an error saying, "Terminating apps," so your app 83 84 00:07:37,660 --> 00:07:47,260 crashed, "because of a reason the delegate must respond to locationManager:didUpdateLocations." 84 85 00:07:47,260 --> 00:07:54,050 And you're wondering, "Hey, wait a minute. I did actually respond to locationManager:didUpdateLocation. 85 86 00:07:54,220 --> 00:07:55,940 It's right here. 86 87 00:07:56,080 --> 00:07:57,490 What's going on? 87 88 00:07:57,490 --> 00:08:05,830 Well, the reason is because we have to set the current class as the delegate to be able to register with 88 89 00:08:05,830 --> 00:08:13,630 the locationManager and to be able to respond when requestLocation actually triggers this method. 89 90 00:08:14,110 --> 00:08:21,220 So what you'll find is that if you have the locationManager.delegate = self set after you 90 91 00:08:21,220 --> 00:08:25,840 trigger this method, you're going to end up crashing your app. 91 92 00:08:25,840 --> 00:08:33,160 Now, in addition, if you take a look at the quick docs for request location, it says right at the bottom: 92 93 00:08:33,250 --> 00:08:41,050 "When using this method, the associated delegate must implement the didUpdateLocation and 93 94 00:08:41,140 --> 00:08:42,100 didFailWithError methods. 94 95 00:08:42,100 --> 00:08:45,180 Failure to do so is a programmer error." 95 96 00:08:45,250 --> 00:08:51,900 So in addition to having this locationManager, didUpdateLocationsDelegate method implemented, 96 97 00:08:51,940 --> 00:08:59,110 we also must make sure that we have our locationManager didFailWithErrorMethod implemented. 97 98 00:08:59,110 --> 00:09:03,050 And in this method, all I'm gonna do is just print the error 98 99 00:09:03,130 --> 00:09:04,630 if there were any. 99 100 00:09:05,080 --> 00:09:07,410 And that's the solution to the challenge. 100 101 00:09:07,420 --> 00:09:12,490 The trick of this challenge was to make sure that you set the WeatherViewController as the delegate 101 102 00:09:12,760 --> 00:09:19,740 before requesting the location and also to make sure you've implemented the required didFailWithErrorDelegate 102 103 00:09:19,780 --> 00:09:21,760 method. 103 104 00:09:21,760 --> 00:09:23,560 So, now if we run our app, 104 105 00:09:27,750 --> 00:09:35,250 then you should see "Got location" printed in the console because the locationManager has found the location 105 106 00:09:35,700 --> 00:09:37,620 and they are triggering this method. 106 107 00:09:38,520 --> 00:09:40,530 But where's the permission request? 107 108 00:09:40,560 --> 00:09:41,570 Where's the pop up? 108 109 00:09:41,730 --> 00:09:47,540 Because we've already agreed to share our location to this app, 109 110 00:09:47,550 --> 00:09:49,440 we don't get that pop up ever again. 110 111 00:09:49,440 --> 00:09:54,870 We only see it once. And once you've agreed to it, then you don't need to touch it anymore. 111 112 00:09:55,290 --> 00:10:01,980 If you ever need to change it, then you can go into the settings of the simulator or your phone privacy 112 113 00:10:02,130 --> 00:10:10,170 location services. And here under your app Clima, you can see "Never," "Ask Next Time," or what we've agreed 113 114 00:10:10,170 --> 00:10:18,510 to at the moment "While using the app." So what if instead of printing "Got location data," we can actually 114 115 00:10:18,510 --> 00:10:23,360 print out the actual location of where our simulator is located, 115 116 00:10:23,400 --> 00:10:25,030 terms of the longitude and latitude. 116 117 00:10:25,200 --> 00:10:26,680 How would we do that? 117 118 00:10:26,700 --> 00:10:35,910 Well, notice how when the locationManager calls this method, it also passes in this "locations" input. 118 119 00:10:35,910 --> 00:10:44,570 And this is an array of CLLocations. We can get hold of the last location that they added in there. 119 120 00:10:44,850 --> 00:10:50,510 So we'll just call it location and we'll set it to equal locations.last. 120 121 00:10:50,520 --> 00:10:53,460 So that's the last item in the array. 121 122 00:10:53,460 --> 00:11:01,110 And generally, the locationManager will try to get the current GPS location and hone in on a relatively 122 123 00:11:01,200 --> 00:11:03,150 accurate version of it, 123 124 00:11:03,150 --> 00:11:07,900 so you might end up with several locations. By fetching the last location, 124 125 00:11:07,920 --> 00:11:14,760 we should be able to get the most accurate one. But because this locations.last is an optional, 125 126 00:11:15,210 --> 00:11:23,550 in order to use it, we should first optionally bind it to a new constant called location, so that we unwrap 126 127 00:11:23,550 --> 00:11:33,210 it. And then within this block, we can create a latitude which will set to equal to location.coordinate.latitude, 127 128 00:11:33,510 --> 00:11:42,930 and then we can create a longitude which is going to be the location.coordinates.longitude. 128 129 00:11:43,200 --> 00:11:43,850 - 129 130 00:11:44,550 --> 00:11:48,160 And now let's try and print out those values: the lat and lon. 130 131 00:11:51,750 --> 00:11:54,300 So let's hit run and see what happens. 131 132 00:11:56,390 --> 00:11:57,360 And there it is. 132 133 00:11:57,380 --> 00:12:04,040 I can see my current location which is London and I've got a latitude of 51.5, 133 134 00:12:04,050 --> 00:12:06,790 a longitude of -0.1. 134 135 00:12:06,830 --> 00:12:11,990 Now, you might be wondering, how are you getting a location data for the simulator? 135 136 00:12:12,560 --> 00:12:19,780 Well, if you're going to debug, there's a section called Location. And here you can set a location for the simulator. 136 137 00:12:19,820 --> 00:12:24,760 I've set mine to Custom Location and added the coordinates for London. 137 138 00:12:24,770 --> 00:12:29,510 You can also change the simulators location, say, to Apple's headquarters. 138 139 00:12:29,570 --> 00:12:33,890 However, the simulator doesn't always pick up the location change right away. 139 140 00:12:33,980 --> 00:12:40,970 And in order for that to go through, you also have to head over to Home. and go ahead and delete that 140 141 00:12:41,030 --> 00:12:53,190 Clima app. In order to run it again, and it will now report the updated latitude and longitude. 141 142 00:12:53,190 --> 00:12:59,190 And if you want to test this, you can also set a custom location with a custom latitude and longitude 142 143 00:12:59,190 --> 00:12:59,610 as well. 143 144 00:12:59,910 --> 00:13:04,770 But again, you'll have to go through the process of deleting the app and rerunning it again. 144 145 00:13:06,000 --> 00:13:13,920 So, now that we've got a latitude and longitude, if we head over to the OpenWeather Map API Docs, 145 146 00:13:13,920 --> 00:13:20,820 you can see that in order to get the current weather data, we can either go by city name or we can also go 146 147 00:13:20,820 --> 00:13:24,440 by geographic coordinates which is what we've got at the moment. 147 148 00:13:24,780 --> 00:13:31,170 And the way to make that API call is using the same URL as what we used previously. 148 149 00:13:31,170 --> 00:13:36,640 But then at the end, we tag on two parameters: a lot and a lon. 149 150 00:13:36,700 --> 00:13:39,140 And notice how the lon is spelled a little bit 150 151 00:13:39,150 --> 00:13:42,720 weirdly. it's L-O-N, rather than L-O-N-G. 151 152 00:13:42,840 --> 00:13:50,580 So in order for our API call to work, we have to be able to match their parameter names. 152 153 00:13:50,580 --> 00:13:53,130 Let's first test it out in the browser. 153 154 00:13:53,220 --> 00:13:59,250 Let's go ahead and go into our WeatherManager and get hold of our weatherURL with our app ID, 154 155 00:13:59,250 --> 00:14:06,460 and our units already set, and then I'm going to paste it into the browser bar, and then I'm going 155 156 00:14:06,460 --> 00:14:14,070 to add another parameter by adding the ampersand symbol, and the first one was called lats will set lat 156 157 00:14:14,160 --> 00:14:18,920 equal to, let's say, 51, which is roughly around where I am. 157 158 00:14:19,020 --> 00:14:24,390 And then let's add another one with the ampersand and this is going to be lon with L-O-N, 158 159 00:14:24,500 --> 00:14:31,080 and this is gonna be equal to -0.1 which is going to be roughly around London. 159 160 00:14:31,080 --> 00:14:35,500 So now if we hit Enter, you can see that we're getting our data back. 160 161 00:14:35,670 --> 00:14:40,020 It's clear skies with a temperature of 19.4. 161 162 00:14:40,140 --> 00:14:41,160 Perfect. 162 163 00:14:41,160 --> 00:14:47,470 Now that it's working, let's try and figure out how we can form this URL string in our code. 163 164 00:14:47,550 --> 00:14:54,960 So down here, we've already got a fetchWeather method that takes a cityName and creates a 164 165 00:14:54,960 --> 00:15:01,200 urlString from it. And then performs the request with that urlString which goes into this method 165 166 00:15:01,560 --> 00:15:08,280 and does the networking using URLSession to fetch some data back from OpenWeather Map. And then 166 167 00:15:08,280 --> 00:15:14,990 we parse the data, and then we create a weather object to pass back to our delegate. 167 168 00:15:15,030 --> 00:15:18,610 So this part is actually completely reusable. 168 169 00:15:18,630 --> 00:15:21,200 It's exactly the same process. 169 170 00:15:21,240 --> 00:15:25,140 So all that we need is another fetchWeather method. 170 171 00:15:25,650 --> 00:15:32,380 So if we go into our WeatherViewController, and right where we get back our latitude and longitude, 171 172 00:15:32,420 --> 00:15:35,620 so I'm going to delete those two print statements, 172 173 00:15:35,670 --> 00:15:44,850 instead, I'm gonna call my weatherManager and I'm going to get it to fetchWeather, but instead of using 173 174 00:15:44,850 --> 00:15:52,440 a cityName parameter, I want to be able to use the latitude parameter and put in the lat constants that I've 174 175 00:15:52,440 --> 00:15:53,410 just got, 175 176 00:15:53,430 --> 00:16:00,900 and then the longitude, which is going to have the long property. And I want to be able to call this method 176 177 00:16:01,350 --> 00:16:08,770 in order to get some weather data. And when this goes through successfully and I actually manage to get 177 178 00:16:08,770 --> 00:16:15,850 the data, then the data is going to come back inside my didUpdateWeatherDelegate method. And it's 178 179 00:16:15,850 --> 00:16:21,850 here where it's going to update our temperatureLabel and conditionImageView without any extra code 179 180 00:16:21,880 --> 00:16:23,160 on our part. 180 181 00:16:23,170 --> 00:16:25,780 So this is a time for your challenge. 181 182 00:16:25,870 --> 00:16:35,530 The challenge is to make this method work and get rid of all of the errors. Write the method 182 183 00:16:35,560 --> 00:16:40,810 fetchWeather with latitude and longitude in the WeatherManager, so that when you run the app, it actually gets the 183 184 00:16:40,810 --> 00:16:43,340 weather for your current location. 184 185 00:16:43,660 --> 00:16:49,030 So pause the video and try that now. 185 186 00:16:49,150 --> 00:16:49,450 All right. 186 187 00:16:49,480 --> 00:16:57,080 So let's go ahead and copy this method and we're going to implement it in our WeatherManager. 187 188 00:16:57,160 --> 00:17:03,990 So down here, I'm going to create another function called fetchWeather. And Swift is totally cool with 188 189 00:17:04,000 --> 00:17:09,670 methods which have the same name as long as they have different parameter names. 189 190 00:17:09,760 --> 00:17:17,470 So this fetchWeather method is going to have the latitude and longitude parameter names and it's going 190 191 00:17:17,470 --> 00:17:19,690 to take two pieces of data. 191 192 00:17:19,690 --> 00:17:23,890 Now, how can we figure out what data type we are going to send over? 192 193 00:17:23,900 --> 00:17:30,070 Well, if we head back to our WeatherViewController and we hold down option and click on latitude or 193 194 00:17:30,070 --> 00:17:33,970 longitude, then you can see the data type of the latitude and longitude. 194 195 00:17:33,970 --> 00:17:36,830 It's something called Core Location LocationDegrees. 195 196 00:17:36,850 --> 00:17:38,770 So CLLocationDegrees. 196 197 00:17:38,920 --> 00:17:44,560 So let's go back to our WeatherManager and assign that as the data type that we're expecting, 197 198 00:17:44,650 --> 00:17:51,130 CLLocationDegrees for the latitude and CLLlocationDegrees for the longitude. 198 199 00:17:51,340 --> 00:17:57,430 And once we get hold of the latitude and longitude, what we're going to do is we're going to create a 199 200 00:17:57,560 --> 00:18:05,410 URLString, and it's going to be equal to an interpolated string that's created the first part being 200 201 00:18:05,410 --> 00:18:12,100 the weatherURL, and then at the end, we're going to tag on the property lat which is going to 201 202 00:18:12,100 --> 00:18:15,280 equal latitude that we got passed in. 202 203 00:18:15,550 --> 00:18:22,570 And then the second property that we need to add is the lon, and remember to check that you've spelled 203 204 00:18:22,570 --> 00:18:24,830 it exactly the same as what I've got here, 204 205 00:18:24,880 --> 00:18:26,960 L-O-N and L-A-T. 205 206 00:18:27,010 --> 00:18:33,100 This is a really common place where students fall down. And then we're going to set it equal to, making 206 207 00:18:33,100 --> 00:18:39,880 sure that there's no spaces anywhere the longitude that got passed over from our location manager. 207 208 00:18:41,110 --> 00:18:48,180 Now that we're done with our urlString, all we have to do is trigger performRequest with 208 209 00:18:48,190 --> 00:18:55,090 our urlString. And it will go through the same process as it did before with the cityName to network 209 210 00:18:55,180 --> 00:19:02,260 and pass the data, and then trigger our delegate method didUpdateWeather which will update our temperatureLabel 210 211 00:19:02,260 --> 00:19:04,910 and our conditionImageView. 211 212 00:19:04,960 --> 00:19:07,510 So let's hit run and see this in action 212 213 00:19:10,790 --> 00:19:17,990 So you saw it immediately update with the location-based temperature and condition. 213 214 00:19:17,990 --> 00:19:25,910 And now if I go ahead and type a city, say, Paris, you can see that in Paris, it's thunderstorms. That also 214 215 00:19:25,910 --> 00:19:33,320 works. But how do we get back to our location-based weather? And how can we update our cityLabel to be 215 216 00:19:33,320 --> 00:19:41,130 able to tell us which city we're currently in when we're getting our location data? And I want to pose 216 217 00:19:41,130 --> 00:19:42,980 this as a challenge to you. 217 218 00:19:43,080 --> 00:19:48,780 Can you write the last part of the app on your own? Link of the button in the top left, so that when it 218 219 00:19:48,780 --> 00:19:55,320 gets pressed, we get the weather for the current location displayed. Also, the label should update to show 219 220 00:19:55,320 --> 00:20:01,110 the name of the current location. On the other hand, when we type in a cityName, we get the weather for 220 221 00:20:01,110 --> 00:20:07,800 that location and the label will display the name we get back from OpenWeather Map. Linking up the button 221 222 00:20:07,800 --> 00:20:11,480 will be the tricky part. So check the documentation in Stack Overflow 222 223 00:20:11,480 --> 00:20:15,930 to figure this out. I'll give you a few seconds to pause video before I show you the solution. 223 224 00:20:20,740 --> 00:20:21,090 All right. 224 225 00:20:21,170 --> 00:20:22,400 Here's the solution. 225 226 00:20:22,400 --> 00:20:25,770 Let's tackle updating the cityLabels first. 226 227 00:20:25,850 --> 00:20:31,640 Now, if we take a look at the data that we get back from OpenWeather Map, you can see that right at the 227 228 00:20:31,640 --> 00:20:37,520 bottom, we get the name of the location based on the latitude and longitude. 228 229 00:20:38,540 --> 00:20:45,470 So if I go ahead and update my latitude and longitude to my current location, then you can see that it's 229 230 00:20:45,470 --> 00:20:49,380 telling me that I'm currently inside the city of London. 230 231 00:20:49,550 --> 00:20:54,080 So we've already managed to get hold of that name property here. 231 232 00:20:54,110 --> 00:21:00,830 All we need to do is inside our WeatherViewController where we're updating our labels, we should go 232 233 00:21:00,830 --> 00:21:14,400 ahead and set the self.cityLabel.text to equal the weather.cityName property. So now 233 234 00:21:14,460 --> 00:21:17,160 that should populate our citylabel. 234 235 00:21:17,190 --> 00:21:19,050 Let's give it a run, see if that works. 235 236 00:21:22,670 --> 00:21:28,700 And as you can see that the label is now updating using the location name from the JSON that we got 236 237 00:21:28,700 --> 00:21:30,410 from OpenWeather Map. 237 238 00:21:30,410 --> 00:21:34,760 At the moment, I still got my simulator set to Cupertino. 238 239 00:21:34,760 --> 00:21:39,120 Let me change the simulator back to London using the custom coordinates. 239 240 00:21:39,320 --> 00:21:46,430 And now if I simply just quit the simulator and then rerun the app, you can see that it's now updated 240 241 00:21:46,490 --> 00:21:48,810 to use that current location. 241 242 00:21:48,860 --> 00:21:54,650 So switching different location types in the simulator can be quite painful. But hopefully, if you're 242 243 00:21:54,650 --> 00:22:02,350 running this on a physical device, you'll actually be getting your exact current location. So, now all 243 244 00:22:02,350 --> 00:22:08,990 that's left is to be able to switch back to location mode when we have gone to the city mode. 244 245 00:22:09,340 --> 00:22:14,770 So right now I've got my weather for Paris and I want to be able to click on this button to go back 245 246 00:22:14,770 --> 00:22:16,630 to my current location's weather. 246 247 00:22:17,170 --> 00:22:24,160 So in order to do that, the first thing we need to do is to create an IBAction. 247 248 00:22:24,170 --> 00:22:30,870 Here let's create an IBAction that links this button down into our WeatherViewontroller 248 249 00:22:31,130 --> 00:22:39,620 and I'm going to call this action locationPressed, and then change the data type into UIButton. 249 250 00:22:39,710 --> 00:22:46,610 And now I've got my IBAction locationPressed where I can change my app to, again, 250 251 00:22:46,610 --> 00:22:52,230 use the locationManager's location to get the weather. But how do I trigger this 251 252 00:22:52,260 --> 00:22:57,020 locationManager, didUpdateLocations method again? 252 253 00:22:57,270 --> 00:23:04,730 Well, one way of doing it would be to call this requestLocation method again. 253 254 00:23:05,040 --> 00:23:11,970 But if we've already requested the location and we haven't changed our GPS location, then if there's 254 255 00:23:11,970 --> 00:23:14,820 no change, then there's gonna be no update. 255 256 00:23:14,820 --> 00:23:18,240 So this method is not going to get called. 256 257 00:23:18,240 --> 00:23:24,050 And you can confirm this by simply adding a print statement inside the locationManager. 257 258 00:23:24,150 --> 00:23:32,970 So the way to solve this is we want to be able to call locationManager.requestLocation and trigger 258 259 00:23:33,120 --> 00:23:38,300 a reupdate and call this method again so that we fetch the weather. 259 260 00:23:38,520 --> 00:23:46,560 But in order for this to work, once we've gotten hold of the weather, either at the time when we've loaded 260 261 00:23:46,560 --> 00:23:54,060 up our app or at the time where they press the location button, we want to be able to stop the 261 262 00:23:54,060 --> 00:23:54,630 locationManager. 262 263 00:23:54,810 --> 00:24:04,910 So we're gonna say locationManager.stopUpdatingLocation as soon as it's gotten hold of a location. 263 264 00:24:04,950 --> 00:24:12,990 So now the sequence of events is, first, we set our locationManagersDelegate as ourself, then we call 264 265 00:24:13,050 --> 00:24:18,550 requestLocation, locationManager is gonna be hard at work fetching the current location. 265 266 00:24:18,690 --> 00:24:25,230 And once it does, it calls this method passing in the locations that it's found, and we look inside that 266 267 00:24:25,230 --> 00:24:27,610 array to find a location. 267 268 00:24:27,780 --> 00:24:34,050 And as soon as we found one, then we tell the locationManager to stop and we use the location to get 268 269 00:24:34,060 --> 00:24:34,880 the current weather. 269 270 00:24:35,490 --> 00:24:43,070 So at a later point, if we press on the locationPressed button, then it calls this method again. 270 271 00:24:43,530 --> 00:24:50,120 And now our locationManager has been activated once more, so we can call this delegate method again. 271 272 00:24:50,760 --> 00:24:55,410 Let's give that a go and see if it works. 272 273 00:24:55,470 --> 00:25:02,310 The first thing that we see is the current location's weather. And now I'm going to search for another 273 274 00:25:02,310 --> 00:25:09,900 location's weather, see what it's like in Beijing. And now if I want to switch back to location mode, 274 275 00:25:09,900 --> 00:25:16,680 I press on this button and I trigger the request location once more where the locationManager calls 275 276 00:25:16,680 --> 00:25:20,040 didUpdateLocation and I fetch the weather again. 276 277 00:25:20,040 --> 00:25:21,000 So that's it. 277 278 00:25:21,000 --> 00:25:27,330 We've managed to create our weather app that uses the current location to get weather, as well as using 278 279 00:25:27,390 --> 00:25:33,780 the city name that the user types in through the text field. And in the process, we've learned about text 279 280 00:25:33,780 --> 00:25:42,260 field, protocols and delegates, extensions, networking with URL session, as well as parsing JSON data. 280 281 00:25:42,390 --> 00:25:48,690 So it's been a pretty jam-packed module if you ask me. And it might be that you might have to review 281 282 00:25:48,690 --> 00:25:54,860 certain parts of this module over the coming days to be able to really digest it and make it your own. 282 283 00:25:55,740 --> 00:26:01,260 But once you've done that, head over to the next lesson and there'll be a challenge, as usual, for you. 283 284 00:26:02,250 --> 00:26:04,500 And I'll see you on the next module.