Bummer! This is just a preview. You need to be signed in with a Basic account to view the entire video.
Start a free Basic trial
to watch this video
Since the model can construct itself from JSON, the only work we have to do is to figure out if we have any errors and define a completion handler for the call site
-
0:00
Since we have a wrapper type now, the weather model that encapsulates all
-
0:05
of our data, let's modify our method a bit in the DarkSkyAPIClient.
-
0:11
Rename it to start, and you can command click on the method name, and
-
0:14
select Rename.
-
0:16
And we're going to call this getWeather instead, and
-
0:20
we're going to make it private.
-
0:24
In addition, let's right up above it, let's create another type alias.
-
0:29
We'll call this, WeatherCompletionHandler.
-
0:36
The type for this is a closure that accepts an optional weather instance,
-
0:41
an optional DarkSkyError instance, and returns Void.
-
0:46
In our method now named getWeather, we can change this completion handler from
-
0:50
CurrentWeatherCompletionHandler to the new one that defines a weather instance.
-
0:55
Okay, so now we're back in our starting point,
-
0:58
let's define the body of disclosure here in the jsonTask method.
-
1:02
So that once the task is done, it has some code to execute.
-
1:06
Because our JSON can be nil, we're first going to check by
-
1:10
unwrapping it using a guard statement, say guard let json = json.
-
1:16
Now if the JSON is nil, we're going to step into the else clause, and
-
1:20
in here we'll check for an error.
-
1:22
Because we defined the body of the closure in the data task method,
-
1:26
we know that this closure can never be called with both the arguments set to nil.
-
1:30
So if our JSON is nil here, then we absolutely do have an error.
-
1:35
Since the error argument for the completion handler of getWeather is
-
1:39
also optional and of the same type, we can just funnel this through.
-
1:44
So let's say, completion mil for the weather model instance,
-
1:49
and error, from the error right here that we can pass through.
-
1:54
And then as a guard statement, so select and we'll add a return so
-
1:57
that we exit the current scope.
-
2:01
Now back in the current scope, we know we have a valid JSON object, so
-
2:05
the rest is fairly straightforward.
-
2:07
Since we wrote and in it method on whether to create and
-
2:10
instance from JSON, all we have to do is call it.
-
2:13
Again, we'll use a guard statement, attempt to create an instance of whether.
-
2:17
We don't necessarily need to do this, the second bit,
-
2:20
since whether is initializer is fillable, we'll get an optional back.
-
2:25
But because the argument type in the completion handler also has an optional
-
2:29
weather instance, we could simply call it and provide the result nil or not.
-
2:34
The issue in doing that is that if weather is nil,
-
2:37
we don't provide an error at the call site.
-
2:39
So now we do have a case at our final call site where both the model instance and
-
2:44
the error value are nil, which is useless.
-
2:47
So we'll say, guard let weather = Weather,
-
2:49
we use the initializer that accepts json, and we'll pass that through.
-
2:56
For the else clause of this guard statement,
-
2:58
we need to indicate that we failed at parsing the JSON correctly.
-
3:02
Which is just a matter of calling the completion handler providing nil for
-
3:06
the model instance, and indicating that the air is a jsonParsingFailure.
-
3:12
Mean double check that I call that correctly, DarkSkyError,
-
3:17
yeah, jsonParsingFailure.
-
3:20
Okay, and then we'll add a return statement to exit the current scope, and
-
3:23
this is completion, here we go.
-
3:26
Okay, so back at the main scope, we've arrived at our final bit of logic.
-
3:30
We have a valid model instance, so let's call the completion handler again and
-
3:34
pass that as an argument.
-
3:36
Completion handler, weather and nil, and that is it for the body of this closure.
-
3:42
We have now defined what we want to do with the resulting json or error.
-
3:46
Remember that we aren't actually executing anything here,
-
3:49
and no networking call will be made.
-
3:52
And that's because we need to still call resume on the task,
-
3:55
which will do at the bottom, task.resume.
-
3:58
If we call this method, we have an instance of weather to work with
-
4:02
at the end, not current weather which is what we want.
-
4:05
In any case,
-
4:06
since we made this method private, we can call it from our view controller.
-
4:10
To account for that, let's add another method here below it, we'll call this one,
-
4:15
get current weather.
-
4:16
So will say func getCurrentWeather, since that's what we wanted the end.
-
4:21
And the method signature here is the one we defined earlier, that
-
4:24
takes the coordinates and a closure of type current weather completion handler.
-
4:29
So getCurrentWeather at coordinate, of type Coordinate, and
-
4:34
then completionHandler with the local name of completion.
-
4:39
This is an escaping enclosure, And the type is CurrentWeatherCompletionHandler.
-
4:47
Inside the body of the method, we can just call our getWeather method,
-
4:51
this takes a Coordinate, we'll just pass it through.
-
4:56
And then for the completionHandler, we actually do need to provide a body that
-
5:01
defines what we want to do with the potential weather instance or
-
5:04
error object.
-
5:06
So here we'll say, weather error in, we're not gonna do much here.
-
5:13
We'll just call the completion handler, again.
-
5:17
And for the model instance, we'll say weather, and this is optional, so
-
5:22
we'll chain an optional call and say currently or error.
-
5:26
And that wraps things up.
-
5:28
Now you might still be confused, but stay with me.
-
5:31
When we call this method, we're going to recap how all of this works.
-
5:35
In the next video, let's put this networking stack to good use and
-
5:38
clean up the view controller.
You need to sign up for Treehouse in order to download course files.
Sign up