Discover how to give users a great location-aware experience while conserving power across all Apple platforms. Learn best practices for using Core Location, how an App can use and manage Circular and Beacon Regions, defer or pause location updates, and how to use Visit Monitoring to determine the interesting places the user has been. Get an overview of how a user authorizes an App's use of location services.
I'm Brad, and today we are going to talk
about Core Location best practices.
Now just so we're all on the same page,
we're going to start off by talking
about the major features of Core Location.
For veterans of our API, this will be largely review.
But for newcomers, it will be--
well, you'll want to consult the documentation
after this session.
After that, we'll switch over to talking about best practices
for using Core Location.
Now iOS is the only platform where all
of our APIs are available, so it will be our focus today.
However, if you are interested in macOS, tvOS or watchOS,
you might want to stick around, because a lot
of the content will be applicable to those platforms,
and we'll talk about them explicitly at the end.
With that, let's get started talking
about Core Locations, major features.
The first one is the authorization API.
Now, you should know that the authorization API is required
in order to access the user's location.
You've probably experienced this as a user,
if you've ever seen a prompt like this one.
Here, Core Location is asking the user if they'd
like to authorize the camera app to access their location.
We offer two different versions of authorization
that your app can request.
The first one is when-in-use authorization,
and just like it sounds like,
when your app receives when-in-use authorization,
it is allowed to access the user's location whenever it is
We'll define what it means to be in use in just a moment.
If you'd like to request when in use authorization,
you simply call the requestWhenInUseAuthorization
We also have AlwaysAuthorization.
When your app has AlwaysAuthorization,
it is permitted to access the user's location whenever your
app is running.
To request it, you simply use the requestAlwaysAuthorization
Whichever authorization level you choose to request,
you must provide a usage description
in your app's information property list.
Core Location will pull this string out of your info plist,
and display it to the user as part
of the authorization prompt.
So when is your app considered in use?
Well, if your app is in the foreground,
then we'll consider it in use.
This is Potluck, our sample app.
If your app is in the background, but has a blue bar,
then it will also be considered in use.
If you're wondering about the blue bar, we'll talk about that
in just a few moments.
Finally, if your app is handling WatchConnectivity messages,
from a foreground watchOS app,
then it will also be considered in use.
Once your app has received authorization from the user,
it can use our location sensitive APIs.
The first one we are going to talk about is the bread
and butter of Core Location, the standard location service.
It comes in two different versions.
The first version is the single location API.
When you call Request Location, Core Location will do its best
to produce an estimate of the user's position,
and then deliver that to your delegate.
We also offer the continuous location API.
When you call Start Updating Location,
Core Location will produce a stream of location updates,
and deliver them all to your delegate.
Remember to stop your location updates when you're done,
since otherwise Core Location will continue
to compute locations.
We have a few knobs and dials you can turn
to adjust how the standard location service works.
For example, Deferred Updates.
When you enable deferred location updates,
you're telling Core Location that it's acceptable for us
to deliver location updates to your app in large batches.
Sometimes we do this for power reasons.
We also offer automatic pausing.
This is enabled by default.
What it does, is it attempts to detect
when your location session has outlived its usefulness
to some extent.
Let's consider an example.
Suppose the user is using a run tracking app,
and they go for a run, but when they get home, they're tired,
and they just want to take a shower, and they forget all
about stopping their location session.
Now, unless the app was specifically trying
to detect this sort of situation,
it's likely that the user's phone would continue
to compute locations until it runs out of power.
With automatic pausing, Core Location will attempt
to detect situations like this,
and automatically stop the location updates.
Core Location also has special support
for using the standard location service while in the background.
Once you engage one of these special sessions,
Core Location will keep your app running and continue
to deliver location updates to it.
If your app has when-in-use authorization,
we'll automatically display a blue bar at the top
of the screen, thus marking your app as in use, and allowing it
to continue to receive location updates.
An always authorized app will still get this background
running behavior, but it won't get a blue bar.
It's important to remember to stop your location session
when you're done, otherwise it will continue
In order to start one of these background sessions,
there are three things your app must do.
The first one is you must enable background location
in your information property list.
Now, the easiest way to do that is to navigate
to the capabilities tab in Xcode,
scroll down to the background mode section,
and check the location updates box.
Second, you must set your allowed background location
updates property to true.
This indicates that that particular location manager
would like to be able to start a background location session.
Finally, you must start your location updates while
in the foreground.
If you don't start your updates in the foreground,
you won't get this special behavior.
So what happens if you do start your updates in the background?
Well, first off, your app will probably need
AlwaysAuthorization since your app won't be considered
in use at that time.
Furthermore, Core Location won't take any action
to ensure your app continues to run.
So if you have background runtime for some reason,
and you decide to start a location session,
you might get some updates,
but you might also get suspended before you receive all the
information you had hoped to receive.
After the standard location service,
we have our background monitoring APIs.
The first one we are going to talk about is region monitoring.
Region monitoring allows your app to specify a location
that is interesting to it, and Core Location will attempt
to determine whenever the user has arrived at
or departed from that location.
This will continue even if your app is suspended
or in the background, and Core Location will launch your app
into the background if necessary
to deliver information about the event.
We have two different versions of the region monitoring API.
First, we have circular region monitoring.
When you start circular region monitoring,
you describe a circular geographic region
that is interesting to your app, and Core Location will attempt
to detect entries or exits from that circular region.
We also have Beacon region monitoring.
Beacon region monitoring attempts to detect proximity
to iBeacon devices that match a specification provided
by your app.
In either case,
region monitoring consumes a limited system resource,
and so Core Location only allows your app
to install a limited number of regions.
However, keep in mind, if you're writing an app
that uses Beacon region monitoring,
a single beacon region can monitor
from many iBeacon devices.
When you're ready to start region monitoring,
you simply construct a CL region,
either a CL beacon region or a CL circular region,
and then pass it to the startMonitoring(for:) method
on CL location manager.
When you're done, pass the same region to stopMonitoring(for:).
If you want to use region monitoring
to trigger a notification, you might be interested to know
that the user notification framework has special support
for this through their UNLocationNotificationTrigger
The user notification framework is new in iOS 10,
but this functionality was previously available
through UI local notification.
If you'd like to learn more
about the new user notification framework, you might want
to view the Introduction to Notifications session online.
Similarly, the HomeKit framework has special support
for triggering a HomeKit scene in response
to a region monitoring event.
The HM LocationEvent allows you to do this.
If you'd like to learn more about using HM location event,
I would encourage you to view HomeKit session from last year.
You can find it online.
In either case, you only need when-in-use authorization
to use the user notification framework,
or the HomeKit framework special support for region monitoring.
General purpose region monitoring
through Core Location requires AlwaysAuthorization.
Similar to Beacon region monitoring,
we have Beacon ranging.
Now, every iBeacon device broadcasts three components
of information: A UUID, a major ID, and a minor ID.
When a beacon region event fires,
you usually don't receive all three components of information.
Using Beacon ranging, you can fill in the missing details.
Ranging is also useful for determining an estimated range
from the user's device to the iBeacon device.
Now, range estimates are most accurate when your app is
in the foreground, but you can use Beacon ranging
in the background.
If you do, however, keep in mind
that Core Location won't prevent your app from being suspended,
and so you might be suspended before you receive all the
information you had hoped to receive.
As an aside, if you're interested
in using iBeacon devices, I would highly encourage you
to visit developer.apple.com/ibeacon.
Once you agree to the iBeacon license, you'll be able
to download the official iBeacon specification
for what every well-behaved iBeacon device must do.
The next background monitoring API we are going to talk
about is the significant location change monitoring API.
As the name would imply, this monitor's for large changes
in the user's location on the order of about a kilometer.
Since we introduced this, quite a bit has changed
in Core Location, and at this point,
we believe that it's fairly unique.
A lot of apps that use significant location change
monitoring would be better served by visit monitoring.
On the topic of visit monitoring,
visit monitoring deploys sophisticated algorithms
to monitor for places that the user might consider a noteworthy
part of their day.
That's why we think many apps would be better served
by visit monitoring.
After all, you're usually interested
in where the user stops and spends time,
rather than where they happen to be
when Core Location has detected a large change.
We've gone to great lengths to ensure
that visit monitoring has a fairly low power cost,
and so you should feel comfortable using it
in an all-day scenario.
Like the rest of our background monitoring APIs,
visit monitoring will continue even when your app is suspended,
and will launch your app in the background
to deliver event information.
If you'd like to start visit monitoring,
you simply call the startMonitoringVisits method.
When you're done, call stopMonitoringVisits.
The final API we are going to talk
about today is the geocoding API.
Core Location supports both forward geocoding,
that is converting an address into a coordinate,
and reverse geocoding, which is converting coordinates
into an address.
Unlike the rest of the APIs we have talked about today,
geocoding does not require user authorization, however,
if your app is authorized to access the user's location,
will automatically use that information
when performing forward geocoding.
That is, converting an address into coordinates.
The geocoding API is rate limited,
and so you should try not to send too many requests to it.
A great way to avoid hitting the rate limit is the cache results
provided by the geocoder.
That way, you don't have to try
to geocode the same information multiple times.
We also recommend that you only geocode
in response to a user action.
For example, if the user drops a pin on a map,
that's an excellent time to geocode that location.
Okay, now that you're familiar with all of our APIs,
let's take a look at authorization again.
If your app has when-in-use authorization
or always authorization,
it can use the standard location service,
those special background location sessions, remember,
that is starting in the foreground
and then entering the background, and Beacon ranging.
If your app has always authorization,
it can additionally use our background monitoring APIs.
That is region monitoring, visit monitoring,
and significant location change monitoring.
Don't forget that the user notification framework
and the HomeKit framework allow you
to do special purpose region monitoring
with when-in-use authorization.
As far as availability is concerned,
all of our APIs are available on iOS.
On macOS, you can use the standard location service,
circular region monitoring,
significant location change monitoring and geocoding.
On watchOS, we support the standard location service,
and geocoding, and finally, on tvOS,
you can use the single location API, and the geocoding API.
Alright, let's get started talking about the best practices
for using Core Location.
The user's privacy is the most important part
about using Core Location.
Location information is highly sensitive.
It describes where we live, where we work,
and who we spend our time with.
As such, you must respect the user's privacy
when using Core Location.
And that is worth repeating.
You must respect the user's privacy
when using Core Location.
Core Location helps facilitate this using our authorization
system, but getting the user's permission
to access your location, sorry, their location,
is only the first step in respecting their privacy.
You should make sure that your app doesn't request any more
information than what it absolutely needs in order
to satisfy a user request.
Similarly, you should make it clear
to the user what you're asking for
and how you intend to use it.
There are two concrete things that your app should do
if it is going to use Core Location.
First if you're going to talk to a server you should attempt
to anonymize those queries as much as possible.
Let's consider an example.
Say you're writing a check-in application.
Well, if the user has tapped the Check-in button,
then it makes sense that you should send both user identity
information and location to your server all at once,
since the user clearly wants your server to know both.
However, if you're writing, say, a weather application,
then the user probably doesn't gain much benefit
from your server being able
to associate both identity and location.
And so the user would be better served
by an anonymous query in that instance.
Additionally, if you plan on persisting location information
to disc, you should use the file protection APIs.
Now this one is relatively simple,
since file protection is enabled by default since iOS 8.
However, it is still possible to create unprotected files,
and so you should make sure that if you're going
to be persisting location information, you should not do
so in an unprotected file.
After privacy, power is the second most important thing
to consider when using Core Location.
The power cost of using Core Location is highly variable.
At one extreme, we have Beacon region monitoring, which is,
for all intents and purposes, free.
And at the other extreme,
we have continuous location sessions,
which can drain the user's battery in just a few hours.
No matter how cool your app is,
if it drains the user's battery faster than they would expect,
they're not going to enjoy using it.
Thus, you must design your app with power in mind.
Sometimes that means sacrificing accuracy or latency in order
to achieve the power metrics that your users would expect.
To achieve that, you must use the right API.
But Core Location has a lot of APIs.
How do you know which one is the right one?
I put together a simple decision tree
that should help guide you toward the right API.
It's not meant to capture every possibility,
but it should be enough to get you started.
The first question to consider is whether you want the user's
location now, or sometime in the future.
If you're interested in the future, then you want to use one
of our background monitoring APIs.
Either region monitoring, if you're interested
in a specific location, or visit monitoring if you're interested
in any location that the user stops at.
If you want to know about the present, then you want
to use our standard location service.
Now, there's a lot of different ways you can use it.
So let's drill into some specifics.
If you're writing a fitness application,
then we recommend you use deferred location updates
in a continuous location session.
If you're writing a navigation application,
then you probably want to use a continuous location session.
If your app is continuously updating UI,
then you also probably want
to use a continuous location session.
The final question to consider is whether your app is recording
a track of the user's location.
If it is, then we would recommend you use deferred
In most other situations,
we would recommend using the single location API.
You may have noticed the battery icon
at the bottom of this slide.
These aren't meant to be taken literally, they're just a guide
to give you a rough idea of how much power each service uses.
Okay, for authorization,
we highly recommend you use when-in-use authorization
Users like knowing that you can't track them
without their knowledge.
Furthermore, you should communicate with your users
and make sure they understand why you're asking
for the authorization level you are,
and how you intend to make use of it.
Remember, Core Location displays a prompt
that includes a usage description key provided
by your app.
This is an excellent opportunity to communicate with the user,
but hopefully it's not the last opportunity you'll take.
Your app should be prepared to direct users to settings.
Core Location only displays a limited number
of authorization prompts for your app, and so at some point,
if you want your authorization level changed, users will have
to go to settings and do it themself.
If you direct your UI application
to open the UI application, open settings, URL string constant,
then iOS will display your apps settings pane.
For Potluck, our sample app, it looks something like this.
As you can see, the user is just a few taps away
from changing Potluck's authorization.
We've seen a lot of developers get confused by Core Location
and it's threading requirements.
The first thing to remember is that Core Location requires you
to create your CLLocationManager on a thread that has a runloop.
When the location manager is initialized, it will determine
which run loop is associated with the current thread.
It will then deliver all delegate callbacks
on that runloop.
Now, for many applications,
the main thread is the only thread with a runloop.
As such, it is safe to create your location manager
on the main thread, but if you do, be careful.
You have to keep your main thread active
in order to handle UI events.
If you spend a lot of time processing location information,
then your app will become unresponsive.
We recommend that you always interact with location manager,
that is, call its methods from the thread
that it was created on.
We believe this simplifies interactions
with location manager.
Let's look at some code.
Here I am requesting authorization.
Let's suppose I've already added the necessary usage description
keys to my information property list.
Here, I'm creating a location manager,
and I'm calling request when-in-use authorization.
Unfortunately, this won't work.
the requesWhenInUseAuthorization method is asynchronous,
and CLLocationManager when it is deallocated will automatically
tear down any outstanding authorization prompts,
and so the user probably won't see the authorization prompt
at all, since the manager will be deallocated
at the end of the function.
Let's try something a little different.
If we put it into a static class property,
then it will certainly live long enough.
However, this introduces a new bug.
See, Swift will initialize the manager property the first time
And unless we're very careful and ensure we always access it
from a thread with a runloop,
this could create a location manager
on a thread without a runloop.
We believe this pattern is error prone and discourage its use.
One more try.
Here, we are creating our location manager
as an instance property on a ViewController.
Now, view controllers are always constructed on the main thread,
and in this instance,
the location manager will be created along
with the ViewController.
So we are guaranteed that the location manger will be
constructed on the main thread.
This is the recommended pattern for creating location managers.
You might also consider attaching it
to your app delegate instead.
Now since the standard location service can be the most power
hungry of all of Core Location's APIs,
it's important to use it correctly.
First we recommend using the request location API
Second, you should ensure
that your desired accuracy property is set
to the largest value your app can tolerate.
Generally, more accurate locations require more power
As an example, if you request, say, 100 meter accuracy,
Core Location usually doesn't need to turn on the GPS in order
to satisfy your location request.
Keep in mind that Core Location will give you
or could give you a location update that is more accurate
than what you requested.
So to say you request a 3 kilometer accuracy location.
This will effectively ask Core Location
to give you whatever location is most readily available.
We encourage you to keep automatic pausing enabled.
We've tuned the automatic pausing algorithm
to be fairly conservative.
We would be surprised if it stopped your location session
at a time when the user was still gaining benefit from it.
As long as you've configured it correctly, you should be able
to leave it running all the time.
To configure automatic pausing,
simply set the activity type property
on your location manager to the appropriate value.
If you'd like to learn more,
you should consult our documentation.
Similarly, we recommend leaving
or enabling deferred location updates.
Deferred location updates allows Core Location to put the device
into a low power state
and collect location information passively
and then process it in large batches.
This can result in a fairly large power savings compared
to a normal continuous location session.
If this is all a little confusing,
and you're not entirely sure how each
of these settings plays out, you might want
to consider using the energy log instrument in Xcode.
This will give you a rough idea
of how much power your continuous location sessions
Finally, we recommend that you set the
allowsBackgroundLocationUpdates property to true only
when you're sure that you want
to begin a background location session.
We've seen some apps set it to true unconditionally
and then just stop their location sessions
when they enter the background,
but this has a negative side effect.
Here, I've modified Potluck, our sample app, to do exactly that.
You'll see that when I start the session and then home out,
there is a blue bar at the top of the screen
for just a few seconds.
So here I am starting the session.
Then I hit the home button, and there is a blue bar
at the top of the screen.
This can be easily avoided
by simply managing your allowsBackgroundLocationUpdates
Now, our monitoring APIs affect your entire process.
As such, we recommend that you always interact with them
from a single location manager, shared by your entire process.
You might want to attach it to your app delegate.
Furthermore, our monitoring APIs will continue
until you tell it to stop.
This is true, even if you update your app
and remove all references to Core Location
and stop linking the framework.
So we highly recommend that whenever your app is launched,
you take a moment and assess whether you think Core Location
should be doing background monitoring for your app.
Unless you're sure that at
that time background monitoring should be running,
you should tell Core Location to stop monitoring.
This small snippet of code is all it takes to stop all three
of our background monitoring APIs.
If you're writing an app for an indoor venue,
you should remember that Core Location will automatically
enable indoor location technologies whenever your app--
sorry, whenever the user-- is inside your venue.
This only happens if your venue has been surveyed.
If you'd like your venue to get surveyed,
go to mapsconnect.apple.com to learn more.
Beacon region monitoring is a highly versatile technology
that can be used in all sorts of problem domains,
but we think it pairs especially well with indoor scenarios.
It complements indoor location very well.
Beacon region monitoring allows your app to detect proximity
to landmarks that you've established inside the venue.
Indoor location allows you to display the user's location
on a map, and help them navigate from one location to another.
On watchOS, you should remember
that Core Location will automatically leverage the
iPhone if it's nearby.
Let us handle talking to the iPhone
and using it to compute locations.
Furthermore, we've seen a lot
of apps request always authorization on watchOS,
even though what they are doing could be accomplished
with when-in-use authorization.
If you're thinking of using always authorization on watchOS,
we would encourage you to take a second look
at when-in-use authorization.
For watchOS 3, we are making startUpdatingLocation available
However, most apps would still probably be better served
There is an exception, though.
In watchOS 3, we've made background
on watch possible for fitness purposes.
So if you're looking at creating a workout application,
that startUpdatingLocation is the perfect API or you to use.
For macOS, we only support always authorization.
Furthermore, Core Location will automatically display a prompt
when you attempt to access location information.
You don't need to call requestAlwaysAuthorization
Since Macs don't tend to move around very much,
we believe that requestLocation is usually the API you want
to use on macOS.
For tvOS, you have got three powerful APIs,
Single Location, Geocoding and MapKit.
Using these APIs, you've got everything you need
to create a great location aware experience on Apple TV.
But be extra careful with any information vended
to your application through Core Location;
tvOS devices usually live in a user's home,
and the user's home is among the most sensitive information you
can get from Core Location.
You should treat that information
with the respect it deserves.
That brings us to the end of our session today.
There are four things I want you to remember as you leave.
First, you must respect the user's privacy.
Part of this is communicating with the user
and making sure they understand what you're asking for
and how you intend to use it.
Second, conserving power is an essential part
of using Core Location.
Sometimes you have to sacrifice accuracy and latency in order
to create the experience your users would expect,
while still having the power metrics your users would expect.
To do that, you have to make sure you use the correct Core
Location API for your problem domain.
Similarly, make sure you use when-in-use authorization
whenever you can.
If you're having a hard time getting started
with Core Location, I recommend you take a look
at Potluck, our sample app.
We updated it this year for Swift 3,
so it's looking better than ever.
If you'd like to learn more you can view our supplementary
material online or check out one of these related sessions.
With that, thank you for your time.
Enjoy the rest of WWDC.
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.