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
Once a location manager requests permission or a user's location it uses the delegate pattern to determine the outcome of these events. In this video, let's implement the delegate methods necessary for determining a user's authorization status
-
0:00
In the previous video, we wrote code to indicate that our LocationManager class is
-
0:04
going to act as the delegate to the CLLocationManager instance we defined.
-
0:10
So that we can respond to location events.
-
0:12
We can navigate to the protocol reference in the docs, so Help > Documentation and
-
0:18
API Reference, and the protocol here, CLLocationManagerDelegate.
-
0:24
And in here, you'll see that we can implement methods to respond to
-
0:27
location events, to pause those updates, and so on.
-
0:31
We can do lots of different things. Now to receive the updates our class
-
0:34
LocationManager needs to conform to the delegate protocol,
-
0:38
which we went ahead and did.
-
0:41
So if you didn't, it is the CLLocationManagerDelegate protocol.
-
0:45
We don't get any errors here,
-
0:46
and that's because all the methods in the CLLocationManagerDelegate protocol
-
0:51
are marked as optional, being an Objective-C protocol and all.
-
0:55
Okay, so once you make the request, the LocationAuthorization request,
-
1:00
the LocationManager kicks into gear.
-
1:03
So over here is where we make the request.
-
1:06
It kicks into gear and
-
1:07
then fires off the results to its delegate when it gets it back.
-
1:10
Before we tackle delegate methods,
-
1:12
let's see what this authorization process looks like.
-
1:16
So head over to the PermissionsController, and right after the oauth stored property,
-
1:22
let's add a new stored property, and create an instance of the LocationManager.
-
1:26
So let locationManager = LocationManager.
-
1:34
Now, inside the requestLocationPermissions method, which you can get to easily by
-
1:39
going to the jump bar, and then looking for that one right there.
-
1:42
So inside this method, let's add the following code.
-
1:46
So we'll say do, since remember, this is a throwing method,
-
1:51
we're going to ask the locationManager to requestLocationAuthorization,
-
1:57
which calls the underlying manager's method.
-
2:01
And then we know that this is a throwing method so we need to catch on the relevant
-
2:04
errors, so we'll say catch LocationError.disallowedByUser.
-
2:10
And then over here, you can do something like Show an alert to users.
-
2:15
The compilers are gonna complain because we're not catching all errors, so
-
2:19
let's create a generic catch block.
-
2:22
And I'm just going to print Location Authorization Error:
-
2:32
error.localizedDescription.
-
2:38
Let's give this is a try.
-
2:39
So we'll hit play.
-
2:43
We should automatically get the modal pop-up because we don't have permissions.
-
2:48
And let's go ahead and click Request Location Permissions.
-
2:53
When you do this you should see the permissions alert pop up.
-
2:57
The alert title should say that location is only monitored while you use the app,
-
3:03
since that's the key that we used.
-
3:05
And you should also see the descriptive string you provided as the alert body.
-
3:09
Now before I click Allow here to grant access, remember that we won't be notified
-
3:14
of the result of this permission request immediately.
-
3:17
This is because I don't need to respond immediately.
-
3:20
I could put my phone down over here, and
-
3:22
walk away without interacting with the alert.
-
3:24
Instead, when we do eventually respond, we get notified through a callback.
-
3:29
So far, most of our callbacks that we've used throughout
-
3:32
our courses have been closures.
-
3:34
But CLLocationManager uses the delegate pattern.
-
3:38
You'll remember that we assigned self, that is, this locationManager instance or
-
3:43
the type is going to act as the delegate to the underlying CLLocationManager.
-
3:49
So to react to whatever action the user takes back in LocationManager,
-
3:53
we need to implement a single delegate method.
-
3:56
Now let's stop the app here before we grant access and
-
4:00
we'll implement that method.
-
4:03
The method is locationManager
-
4:07
didChangeAuthorization status, there we go.
-
4:12
In the body of this method, we'll check if it's the success case or
-
4:16
not, if it's the case we care about.
-
4:18
So we'll say if status == .authorizedWhenInUse.
-
4:24
Now, we're not going to handle it here.
-
4:25
We're not going to let the location manager handle it.
-
4:29
Instead, let's create our own delegate protocol and a delegate.
-
4:33
This way, we can let the relevant object handle it,
-
4:35
which in our case is the permissions controller.
-
4:38
So we can let the permissions controller subscribe to these events and
-
4:41
react appropriately.
-
4:43
So up at the top here, after the error,
-
4:46
we'll say protocol LocationPermissionsDelegate:.
-
4:51
We'll make this a class bound protocol.
-
4:56
And we will give it two methods here, two requirements.
-
4:59
And we're going to indicate that either the authorization, so
-
5:04
authorizationSucceeded, or that the authorization, Failed,
-
5:10
and to make it a bit clearer, we'll provide the status that it failed with.
-
5:15
So authorizationFailedWithStatus(_ status: CLAuthorizationStatus).
-
5:22
Okay, so now that we have a protocol,
-
5:24
the next step is to add a delegate stored property.
-
5:28
So in the LocationManager class, we'll say weak var permissionsDelegate:
-
5:34
LocationPermissionsDelegate?, this is an optional property.
-
5:40
And if you don't understand why this is optional or why this is weak,
-
5:43
you should check out the Delegates in iOS course.
-
5:45
Now that we have a delegate, back in our if statement, here in the delegate method,
-
5:50
we can inform the permissions delegate that the authorization succeeded,
-
5:54
because this is the status we want.
-
5:57
So we'll say
-
5:57
permissionsDelegate.authorizationSuccee- ded.
-
6:02
If the status is anything but authorized when in use,
-
6:05
we'll use an else clause to tell the permissions delegate that we failed.
-
6:10
So authorizationFailed and we'll pass the status through.
-
6:14
All we need to do now is assign an object to act as the permissions delegate.
-
6:20
So instead of leaving this as an implicit step and potentially forgetting it,
-
6:24
let's modify the init method of this class to accept a permissions delegate.
-
6:30
So let's get rid of the override keyword,
-
6:32
cuz now we're not overriding any initializer.
-
6:33
And we'll say init permissionsDelegate of type LocationPermissionsDelegate?,
-
6:40
we'll make this optional as well.
-
6:43
And then, before we call super.init,
-
6:46
we'll say self.permissionsDelegate = permissionsDelegate.
-
6:52
Modifying this init method, of course, raises an error in the permissions
-
6:56
controller, so we need to go ahead and fix it.
-
6:58
Which, by the way if you didn't realize, I don't know if you can see it in this
-
7:03
video, but in the scroll bar over here in Xcode, in the corner, when you have
-
7:06
an error, there's a thin, thin red line to show you where that error occurred,
-
7:10
so you can just zoom right over there.
-
7:12
Here we go.
-
7:13
So we have an error here, and we need to change this now to use a new initializer.
-
7:18
We want the permissions controller itself to act as a permissions delegate,
-
7:22
to the locationManager instance.
-
7:25
Which means that when we're initializing the property here,
-
7:27
we need to pass in self.
-
7:29
We can't do that when we do it as a simple stored property, so
-
7:32
instead, let's make this a lazy stored property.
-
7:35
We'll say lazy var locationManager of type LocationManager and
-
7:40
we'll assign a self or an immediately executing closure rather.
-
7:46
And then you will say return,
-
7:50
LocationManager(permissionsDelegate: self).
-
7:54
Obviously, you'll get an error.
-
7:55
Self is currently not conforming to the right delegate protocol.
-
8:00
So we'll go up to the top, class PermissionsController, and
-
8:03
conform to the LocationPermissionsDelegate.
-
8:06
Once you do that, you need to go down to the bottom.
-
8:07
You'll get another error because we're now not conforming to it, so
-
8:11
let's go to the very last method.
-
8:14
And below that, we'll add a comment marker,
-
8:20
Location Permissions Delegate.
-
8:24
And in here, we'll say authorizationSucceeded, and
-
8:28
authorizationFailedWithStatus.
-
8:30
If the user grants permissions, so if this method is called, we need
-
8:35
to update the location permissions button, much like we did for the oauth button.
-
8:40
So we'll say locationPersmissionButton.setTitle.
-
8:47
Location Permissions Granted, for status, or the state is disabled.
-
8:55
And then we'll go ahead and disable the button, oops, right here.
-
8:59
We'll say locationPermissionButton.isEnabled
-
9:05
= false.
-
9:06
Okay, and let's just comment this out for now.
-
9:08
Now, we have an error here for CLAuthorizationStatus, and
-
9:12
that's because we're not importing the CoreLocation framework.
-
9:16
So let's do that really quick up at the top.
-
9:19
Okay, let's run the app one more time.
-
9:23
And let's go ahead and request location access.
-
9:28
Since the alert is shown only if the status is not determined,
-
9:31
if I click Don't Allow, then we're going to hit a failure point.
-
9:35
Now I'm gonna leave that as an exercise for you to implement.
-
9:39
Here's a typical flow.
-
9:41
So if the user clicks deny, you're going to, or Don't Allow, you're
-
9:44
going to present an alert stating that the app cannot be used without location data.
-
9:48
And inform them how to change the permissions in their settings page.
-
9:52
iOS has a method that allows you to link directly
-
9:55
against the app's settings page via a URL.
-
9:58
But again, I want you to figure that out.
-
10:00
Read the docs, check things out, and try to solve the problem yourself.
-
10:05
If you can't, jump to the Treehouse community and ask around.
-
10:08
Let's go ahead and Allow location monitoring.
-
10:11
Nothing's going to happen after that, of course, and
-
10:13
that's because we need to implement the necessary delegate methods to proceed.
-
10:18
Now, I went ahead and restarted my simulator in between a couple videos, so
-
10:21
I don't have the oauth token anymore.
-
10:22
So I'm just gonna click Request again to get it, and there we go.
-
10:26
Now we have both sets of permissions, and I'll Dismiss.
You need to sign up for Treehouse in order to download course files.
Sign up