0:00
[MUSIC]
Okay we've requested permissions we've got our info.plist set up,
now let's set up that location manager and let's set up an initial view of our map.
And then we'll make sure that user tracking is working through
using that simulated file.
So let's do that next.
Go back to our code,
first thing I going to do is I'm going to go to our storyboard.
And what I want to do here is a couple things.
I'm going to select on my Map View, over here on the left, and
I'm going to go ahead and change this from standard to hybrid.
I'd like to be able to see the satellite imagery in addition to the street maps so
that I can make sure that everything is working okay.
If I just see that street maps, it's going to be a little difficult for
me to debug.
Now if we go back to our view controller, what we're doing now in this section,
is we're setting application manager and the map.
All right, so our location manager we haven't even declared a location manager.
And so we need to declare that locally.
So let me go down here and get some boilerplate code for us.
Well it's not boilerplate but it's pre-made code.
1:10
And this is going to be our location manager.
That's going to be a local variable that we keep track of
all of our services that we use to get our services.
And then we're going to initialize our services in our view controller.
So after view did load we're going to set out UI in the appropriate way.
We know right here we need our location manager to be initialized so
we'll initialize it before that code.
So, we'll set up our location manager here.
1:43
getting a instantiation of the location manager.
We want to set the delegate to ourself, meaning that when we get callbacks from
our location manager, we want those callbacks to be handled by our code.
Unfortunately, though we haven't actually indicated that our code can do any of
those things.
So up here we'll say CLLocationManagerDelegate and
that'll say that this is a class that is able to be a delegate.
So now down here when we set this class equal to the deligate
we don't have any errors.
We're going to tell the location manager to allow background location updates and
that has to be mapped by both the permission and the info.plist.
We will allow it to pause location updates automatically and so
that's a way of reducing power usage on your device.
So if it appears that the user is not moving because other sensors like
the accelerometer are very steady, then location updates will be slowed down.
You won't get them quite so frequently.
2:45
In practice, it's just a helpful way of reducing battery life.
We'll say that we would like the most accuracy possible.
Which means that the device will fire up the GPS if it has it.
And that we want to know changes of no more than five meters.
Actually, I'm going to shrink this a little bit.
So what that means is that, if, all other things being equal.
3:06
Even given the GO region code that limits some of this.
I don't want to be told unless our distance has moved more than three meters.
So it's a way of being explicit about how often you want updates.
Okay, so that gives us our location manager code,
and that now enables, right here, enables us to request authorization.
3:36
I guess the next thing that we want to do actually is before we say our map is
completely set up, is we want to put.
If you remember from when we used our map view before we had a variable
that indicated whether the map was being moved by the user or not.
And if it was and we stop updating things temporarily,
so lets add the ability to do that as well.
4:26
We need to implement ourselves as a delegate for the maps.
Let me see if I can get this.
Mk mapviewDelegate.
I think that's right.
I think that's right typing.
Now we need to go to the storyboard, just like right here on our location manager,
we say our location manager delegate equals ourself.
That says that this object that we created, the location manager,
will send its callbacks to this object.
We haven't indicated that we want our map view to send its call backs to this class.
Instead of doing it in code though, we do the same thing via the storyboard here.
And we're going to expand our according.
And we're going to select our map view.
And we're going to control drag our map view to our view controller and
specify that this class is the delegate.
All right.
So now, what we'll do is override the two functions that indicate
that the map is being moved.
So that we can set our map as moving variable.
5:43
So in the first case this is our call back function.
If the region is about to change, meaning the user has initiated a change to
the map, we will get this callback saying hey, we're about to animate,
in which case we'll say the map is moving.
And when the map is moving, we'll turn off some of our updates,
in particular centering the map on location updates.
And then, when the user is done moving,
we will set our local variable to that region.
Region did change to animated, means we're past the change.
Map is moving as no now, and we can do the work that we intended to do.
All right, the last thing that we want to do for
setting up the map is we want to zoom in automatically.
Now, we could do this manually every time we moved in.
But when this testing, it's gotta be very convenient to have that done for us.
I'm getting the beach ball.
That's good, right?
So we'll add some code here to set up.
6:34
After we set up the location manager, we will go ahead and
zoom the map in very close so that we can see the effects of what we are doing.
[SOUND] All right so to do that, we're going to create a coordinate location.
We don't actually use it.
It's just a dummy variable, and
we'll say we want our map generally to be about 500 meters by 500 meters.
We'll adjust that region so
that, that desired resolution fits within the aspect ratio of our device.
Our map viewed is lower case.
So fit it in there.
And then we'll go ahead and this is the command here.
Set region that actually does the zooming.
7:14
All right so what we set up now if we run this
application we should see that our application starts.
We should have a map.
The map should be in hybrid mode.
We should be able to zoom in and zoom around all of our functionality
should be disabled until the point at which we're ask permissions.
At which point it should be enabled, but if we do anything with the switch,
if we do anything else nothing should happen.
because we don't have anything like location updates starting or
anything like that.
So let's run and just make we're doing okay so far.
7:53
Build succeeded, we love that.
Here's our application.
Booting up.
Great. It's asking,
if we would like it to send us notifications.
Eventually, we do, so we're going to say, okay.
And can it use our location even when we're not using the app?
Yeah. That's okay because
see here's my reason that I put in the info.plist file.
We'll allow that.
We're zoomed in, but we happen to be zoomed in on an area of the world that
doesn't have a map resolution at that level.
So, it's a little wonky.
Our UI is a little crazy right now.
Not totally thrilled with that.
8:36
But let's go ahead and keep moving, because it looks okay, enough for now,
we're not done, cleaning up later.
Right, to the next thing that we want to do is, we want to get to the point where
we use that temper that test GTX file that we created,
want to make sure that user tracking works in the simulator.
8:55
So to do that, once we have permission and the user has activated our switch.
What we want to do is, we want to turn on location updates, and
then we want to center the map on those location updates.
So, let's add that code.
So for starters, I'm going to come back here to our story board and
our toolbar and our bar button item and our view.
And the UR switch, and I'm going to start that as being off when we begin, so
we start and it's not operating, and we click it in order to activate it.
And let's see, anything else I want to do?
No, that's good for now.
So go back to our view controller.
All right, so what we need to capture,
is we need to capture the user activating that switch.
So, to do that, we need to connect our switch event
from our storyboard onto our code, and so we'll drag and drop that over to where do
we want to put that function, we'll put it down here after our map we'll put it here.
Now, so, I'm going to drag control drag our switch over to this location here.
And I'll say, switch capped and
10:55
Great. And we're going to tell the location
manager that we want to start updating the location.
Great.
And we don't have a region yet, so that's going to come later, so for the time being
we're not going to monitor our region, that would be where we add our geo fence.
But we want to go ahead and enable our check-in button, although we're not going
to call it check-in button, we're calling it a status check button.
11:25
That's so, that we can check whether we're in or out of our region, and then if
we turned our switch field off, then we want to do every thing in the reverse.
We want our status check.
11:36
Button to be enabled disabled, and
then we want to stop monitoring the region, but we're not doing that yet.
We want to stop updating our location, and
we want to tell our map view that we are not showing our location.
12:12
We're telling our location manager to start updating locations.
What that means is,
as new locations come in, we will be told that the location has changed.
You can go ahead and do something with it.
But what do we want to do?
We want to plot the location of the current user.
In order to do that, we need to show the user on the screen and so, we're going to
need to create a local variable which is the annotation the object that we're
going to keep on the map that's going to keep track of the user's locations.
So let's come down here and grab that, this is code that we don't need.
So here is the code for the annotation that we're going to keep track of locally.
13:11
So we have a local variable, current annotation, after we've set up, let's see,
what do we do.
We set up our user interface, so it is disabled until we get permission,
we say the map is not moving, we create our location manager,
we zoom the map in, we check for permissions.
13:40
We are going to call a method on ourselves that we haven't written yet, so
we're getting an error because of that.
But let's go down and that, and to add our current annotation
what we're going to do is we're going to create a new annotation.
We're going to expatiate it with ala and a nit.
And then, we're going to specific it's coordinate.
And initially the coordinate will be 0,0,0,0 so the middle of Africa.
And we're going to call it my location.
This doesn't come into play, so this is just kind of dummy code.
That gives us an annotation, all right, so it's great, doesn't put it on the map yet.
What we're waiting for is, we're waiting for our location manager to give us call
backs, so that we know where to put the user on the map.
We know how to change that annotation, and then send it to the map view.
14:47
So now our location call backs, when the location has been updated,
this function will be called.
At that point, we want to change the coordinate of our current annotation,
which was our local variable,
to be equal to the most recent update that's being passed in this array up here.
The most recent one is the last one in the list.
This is in case, we batch up several changes at once,
we just grab the last one.
Then we want to indicate, we want to check to make sure our map is not moving.
If the user's not moving the map then we're going to want to center it.
We're going to want to center it on the current annotation.
15:21
So far, so good, however we don't have the code to center the map yet.
Fortunately, it's right here, just like a cooking show.
We've already done that.
So a location callback, so we're going to put it up here,
since it's not a location callback.
So to center the map, what we need to do, we need to find the map view and
we want to center it's coordinates on the center point,
which is being passed as a parameter, it's coordinate.
And we want to animate that.
So down here when we pass the annotation, it'll get centered.
So, let's see.
If I'm not forgetting anything.
What we have now is we have an application that when we hit the activation switch,
that is going to cause location updates to start flowing in.
When location updates start flowing in, we'll get callbacks, and
we'll try and center the map on those locations.
So if we run it right now, what we're going to see is that nothing happens,
because there's no simulated track being passed to the simulator right now.
Let's go ahead and do this, good, so far so good.
Hit activate, all right, and now there's no location being passed to that phone,
the phone doesn't have any simulator location.
Now, in the past, we have come up here, and we have done debug, and
we changed location, and we've specified something like freeway drive.
And this is the built in GPX file, for
example, that drives around Apple somewhere in the Bay Area of California.
16:54
There we go, so this shows a track of someone driving on the freeway.
That's fine, and we could use that if we wanted for our testing, but
I want to use the specific track that I already set up.
So this is how we do that.
17:07
If you'll recall, we want to make sure that user tracking works, and so
we need to import the track we created, and then simulate and test that.
So let's go back to our code and do that.
All right, we'll let this run for a second.
The place where we go to do that is not within the simulator, surprisingly.
We've come down here to this little location arrow, and we select it.
And what we can do is we can select any of these locations.
If we want our phone to be in London, England, we can select London, England.
And then if we go back to our simulator, we see that our Xcode has
overrided the location being provided by the simulator and
is forcing our phone to think that it's in London, England.
That's good if you want to test London, England.
It happens to be a single point, it doesn't move.
So if we come back here to Xcode,
and we select our location icon, we can add a GPX file to the project.
And so this,
I'm going to add that GPX file that I created during the previous lecture.
Stored on my desktop, it's called trace.gpx.
It's going to actually bring it in as a resource to my project.
I'm going to go ahead and just add it, and right.
18:15
I can click on it and use it.
And then down here on my arrow, I now have that as an option for
the route that I want to take.
Now if I was clever, I might call it something more meaningful than trace, but
I'm just going to click on trace.
And now, when we go back to our simulator, you can see that,
there we are, next to the ballpark.
And you can see that the simulated location is moving from next to
the baseball field, along the path that I indicated, at the rate that's necessary so
that it will arrive at each point at the right number of seconds or
minutes after the previous point.
19:18
And that's good for simulation, because that's how real location data works.
And it's not moving very fast, that kind of surprises me.
Maybe I have an error in my trace function,
let's go take a look at it real quick.
There we go.
Just a little slower than I expected.
All right.
19:40
So that is making sure that user tracking is working.
We imported the track, we simulated and tested it.
So the next thing that we need to do is we need to do this Geo-Region stuff that
we've been talking about all along, okay?
Thank you.
[MUSIC]