If you do any mobile development, chances are pretty good that you'll want to utilize location tracking. While Apple has a good bit of documentation on the topic, one thing is missing: pragmatic usage of location services. For instance, there's no clear direction on when you should update the location in your app, and that will certainly vary from app to app depending on your use case. Beyond that, which location service should you use? Apple provides a couple of options, so which one is best for your app? Battery usage is always a concern when it comes to tracking a user's location. Do you really need to use GPS or is a less precise (less power hungry) location via Wi-Fi sufficient? And how are you going to tell your users what you're doing with their location. Many users are wary of sharing location information for privacy reasons, but some of those same people will also allow access to their locations if they understand exactly what you're doing with that information.
The first place to start, before writing any code, should be the Location Awareness Programming Guide that Apple has provided. Apple does a great job of introducing developers to the concepts and services they've laid out so you can start making some of these decisions. Next, you should consider how you will use a user's current location. Are you using it to search for things his/her immediate area? Perhaps you are calculating distances or providing a sorting mechanism. Does it need to update constantly? Or can you get it once and reuse it throughout your app?
You'll learn from Apple's documentation that they have provided 3 different location services to track a user's location.
- Standard Location Service: uses GPS, cell, and Wi-Fi to determine connection; most accurate; requires more power
- Significant Change Location Service: uses cell signal only; low-powered option; iOS 4.0+
- Region Monitoring Location Service: monitors boundary crossing for a defined region; iOS 4.0+
The standard location service is the most well known service. It is also the most power hungry, so be sure to evaluate whether you really need this level of accuracy. The significant change service is better suited for scenarios where you need to track the location constantly. If you have an app that is tracking a route, this is a great option because of its lower power requirements. Additionally, this can run even when the app is in the background. The region monitoring service will monitor a user's location, and will dispatch notifications when the user enters or exits the region specific. This could be useful if you want to send notifications, change phone settings, or wake your app up when your user moves into a particular region. For more detail and demonstrations of these services, check the WWDC 2011 session 500 What's New in Core Location.
Which one you choose depends on what you're doing with the location data. Using more than one service at the same time is not recommended since the services listen for location updates the same way. I recommend putting all location code in a single class so you can simply manage location tracking. You don't want to manage 5 instances of the CLLocationManager that could be draining battery by overusing GPS or other radios. Additionally, you can encapsulate the CLLocation work in one place. You could go so far as to employ the Singleton pattern, but that's outside the scope of this post.
Once you identify the appropriate location service to meet your app's requirements, there are a few other things you should consider:
- What if the user turned off Location Services on his device?
- What if the user denies location permissions to your app?
- What if no location can be found (maybe the user is in a basement, parking deck, or the subway) after a minute, 2 min, 10min, etc.?
- Did you know MKMapView's showUsersLocation attribute also triggers location tracking? If you're using a map that has that attribute set to YES, you’ll need to be sure to set it to NO when the map view disappears
It's really important to avoid allowing your app to get stuck in a state where it's endlessly tracking the user's location. Burning battery is a sure way to attract bad app reviews. You may find your app in this scenario if the phone can't get an accurate enough location to meet the requirements setup by the CLLocationManager. You should set the desiredAccuracy to the highest level your app can withstand, and use the distanceFilter to get a location (do you really need the best location w/in 100 meters?). That still doesn't guarantee the device will get a location. If your user is in a parking deck or a basement or maybe a building with really bad service, the device may never get a location that meets the accuracy and distance requirements. It's a good idea to use NSTimers or the dispatcher to stop location tracking if a location can't be acquired within a reasonable amount of time.
In the following code sample, I use a timer that allows the location manager to search for a location up to 10 seconds before I stop the service.
As you can see, I'm using a distance filter of 1000m, which is a little more than .5 mile. That level of accuracy is acceptable for calculating distances in this app scenario, and it gives the location manager a slightly bigger field to hone in on. You also want to keep in mind the phone might return the same location it had before. In my code above, I allow the tracking to continue if I get the same location as before in case the phone lags in updating the location (a common occurrence).
The final consideration in implementing location services is user education. As developers, we frequently forget that users don't automatically know what our app is supposed to do, and what it may be doing in the background. We must take any opportunity we can to inform our users if they have disabled features that our app depends on. Apple gives users full control over what apps have access to location services on the device, and we have to respect that.
Use the following bit of code to check to see if location services are enabled, and that the app has been granted permission to use location services.
If location services are important in your app, you'll want to explain to users why those features aren't working in the event they've disabled location services or simply prevented your app from using those services. An alert is the simplest approach, but you can really implement it however you wish. The goal is to educate your users. Additionally, you should set the purpose attribute on the CLLocationManager (available iOS 3.2-5.x) or add the NSLocationUsageDescription key (available iOS 6.x) in your info-plist. The value of this property is what iOS displays whenever the user is prompted to grant permission for the app to use location services. This is another education opportunity you don't want to miss.
All in all, the location services that Apple provides are more robust than ever. There are several options available for a variety of scenarios, so be sure to take a close look at your users' needs and make the best decision for them. Ultimately, your users have control over whether your app gets access to their location, and it's important to make it worth their while (and their battery life!).