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.
