Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: tech-talks-2011-14
$eventId
ID of event: tech-talks
$eventContentId
ID of session without event part: 2011-14
$eventShortId
Shortened ID of event: tech-talks
$year
Year of session: 2011
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2012] [Tech Talk World Tour] Ma...

iOS 5 Tech Talk World Tour #14

Maximizing Location Awareness on iOS

2011 • 38:08

Geofencing enables pinpointed geographical context within your app. See how to leverage the power of the Core Location framework by using region monitoring and geocoding to create a narrowed location-relevant experience for users. Learn best practices and testing techniques that will help you anticipate different scenarios your users will encounter.

Speaker: Jake Behrens

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

I'm Jake Behrens, Apple's UI Frameworks Evangelist. Adding Location Awareness to your iOS application can make for some incredible user experiences. Today, you're going to learn how to use region monitoring to create more personalized experiences for your users using geofencing. Then, you're going to learn about geocoding on iOS to display location-based information in a meaningful way to your users. Finally, you're going to see how to use Xcode and the iOS Simulator to make the most out of testing your location-aware applications. Let's get started.

Maybe you're displaying a map that shows the user's location in relation to other points of interest, or where their friends are. Or maybe you're using a set of coordinates to display relevant information to the user about where they are. Both of these user experiences make the application more valuable to the user.

But how do you take this functionality farther? You make the experience more personal and more meaningful to the user. Setting a reminder with Siri is a great example of this. The reminder is more personal because the user doesn't have to add an address, they just say work for the location. It's also more meaningful because work is in a language that the user understands. If this phone's locale was set to Germany, the text would also be in German, meaning that the user doesn't have to guess at what this information is. represents.

One more important aspect of location-aware applications is testing. You need to test your application to make sure that the experience is great the first time a user launches your application. You need to test not only where you are, though, but other places your users will use the application in. You want to ensure a great experience for everyone.

So let's start with geofencing on iOS. If you haven't used geofencing, you may be asking, what is geofencing? Geofencing is where you take a point and you map this point to a physical location, maybe on a map. Then you use that point as a center coordinate for a virtual perimeter, a geofence. Then, when a user moves in or out of this virtual perimeter, your application responds with an action. Let's see this in action. Once the user moves, they end up reaching the bounds of a region and are prompted by an application to conduct an action.

A great example of this on iOS 5 is with the Reminders app. You can set a location and add a geofence around it so that you're prompted to do something when you either leave this geofence, the virtual perimeter, or when you enter it. You can see here I've set a reminder for when I leave my current location.

You create geofences using the Region Monitoring API on iOS 5. This API allows you to register regions, these virtual perimeters, using a coordinate and a radius. Then your application can receive a callback when the user enters or exits a specific geofence. Some of you may be saying, "We've had region monitoring on iOS 4." And you're right, we did. But on iOS 4, we used cell towers as our way of triangulating your position and then firing region events.

Well, I'm happy to tell you that on iOS 5, we've added Wi-Fi and GPS to the equation. So now we're using all available hardware sensors to triangulate your position and provide much higher accuracy for region monitoring. So what's new under iOS 5? Improved accuracy. Due to using all of the sensors in your device, in some situations, it can be up to 10 times more accurate.

And I'm not talking about newest hardware only. This is using the same hardware you've been using region monitoring on already. We've just added more capabilities for improved accuracy. We've also added some more informational API. When you register regions, we will look at the region monitoring and the region monitoring data. This will let you know what the status is of that registration. So let's jump right into setting up regions or geofences with region monitoring.

As with other location services, you first need to add the Core Location framework to your application. You'll also need to add a delegate object that will receive the delegate callbacks later on. This is usually your app delegate or a view controller. Then, you need to create a SEAL Location Manager object.

Now, I'm not going to go into too much depth on how to set up and configure your Location Manager. This is a topic we've discussed many times at WWDC, and if you've never used the Core Location framework before, I highly suggest you read our Location Awareness Programming Guide on the Developer Center or watch previous WWDC sessions. Now, finally, your delegate object needs to adhere to the SEAL Location Manager delegate protocol. This makes sure that the Location Manager can fire those delegate callbacks later. With that, you're ready to start creating and registering regions.

You also want to make sure that you're checking to see if the device even allows for region monitoring. Some older devices don't, so you need to check the Region Monitoring Available Boolean on the Location Manager to make sure that you can start monitoring regions. Next, you want to check what the authorization status is for location services. Users can set this in the Settings app, and we'll talk later about the different values and what those can mean.

You start creating a region by creating a center coordinate. So here, you need to create a seal location coordinate 2D with a latitude and longitude. Then, you need to create a seal region object. You do this by calling init circularRegionWithCenter, handing in that center coordinate that you just created, radius, defining how big you want the radius to be for this geofence. Now, we have some constants you can use, but you can also just define this in meters.

And finally, identifier. The identifier is a crucial part of creating a region. It's not something that is going to be displayed to the user, but it's a property on a region that you can check when you get a seal region object passed in with a delegate callback. This allows you to know which region triggered the event, and then you can respond accordingly. So, here, we have a region with a latitude and longitude. And here, we have a region with a latitude and longitude. And here, we have a region with a latitude and longitude.

Finally, you can register the region with Location Services by first creating the CLRegion object, which you just did, and then you call startMonitoringForRegion, handing in the region object that you just created. You call this on the Location Manager, and it's going to talk to Location Services to register the region. So let's see that in action.

When your delegate object creates a region, that object is then handed to the Location Manager to register with Location Services. The Location Manager then hands that region object to Location Services to be registered. And finally, Location Services hands the region object back to the Location Manager, and the Location Manager hands that same region object back to the delegate as a parameter of a delegation.

get call back. If the region was successfully registered, you will get the Location Manager Did Start Monitoring for Region callback. You can then check that identifier property of the region object and see which region was registered with the OS so that you can update your UI if needed.

In the event that the region could not be registered, you're going to receive the Location Manager "Monitoring did fail for region with error" callback. Again, you can check the identifier of the passed-in CLRegion object to see which region was unable to be registered. And that's it. That's all there is to setting up regions.

Now you wait for your user to move around the world, and you'll be able to respond to two different events. The first event is Location Manager Did Enter Region. This means that the user has entered the region you've registered. The second is Location Manager Did Exit Region, meaning that the user has left the region. Now both of these methods include the Seal Region object so that you can, again, check the identifier of the region and respond accordingly within your application.

Now I mentioned earlier that you need to check the authorization status when setting up regions. You can see here that the application has prompted the user to use their current location. Now, this permission dialog will include the name of your application. But you need to plan for the user tapping "Don't allow." They may not know why your application wants to use their location.

Maybe it's not obvious from the type of application that they've downloaded that it needs to use location services. But this is your chance to be as informative as you can to the user. Here what you can do is you can use the Purpose property on the Location Manager.

And the Purpose property allows you to provide a string into the prompt and let the user know why you need to use their location. Maybe it's because the application isn't the type of application that would normally need to use location services. By using the Purpose property, this allows you to give more information to the user and let them decide how they want to respond to using their location within the application. Now, once the user accepts to use location services within the application, the user will see a purple arrow in the status bar when the application is currently using their current location.

The user can also go to Location Services in the Settings app and change the location services for the device overall or for individual applications. They have an enabled switch for the device overall, but they can also see the list of applications that want to use their location. Additionally, they can turn location services on or off per application.

And a location arrow lets them know which applications have used their location information within the last 24 hours or which applications are currently using that information. If it's been used in the last 24 hours, the location arrow will be gray. If the application is currently using their location data, the arrow will be purple.

You can check this authorization status by checking the Authorization Status property on Location Manager. You can also respond to the Location Manager did change authorization status delegate callback when the user changes their options. These are the authorization statuses available. Not determined means that the application can use location services and the user hasn't been prompted yet. So you can try to use their location and the user will be prompted at that time. Additionally, authorized means that they've tapped OK and the application can use location services.

Denied means that they've either tapped Don't Allow for your application, switched it off in location service settings, or they've turned it off for all applications. Now, whether they've turned it off for just your application or for the device overall, the end result is the same, and you should just respond accordingly.

Finally, there's restricted, which means that the user can't authorize the application. Now, this would be in a situation where maybe due to parental controls, the user is not able to actually change location service settings. So in this case, you don't want to hound them to change their settings because they can't. You should just do the right thing.

So as I said, you want to make sure that you do the right thing for when users tap Don't Allow. Your app needs to continue to function and not just sit at a blank screen if the user declines location services. You also need to make sure that the application will degrade gracefully and still continue to work for the parts that don't require location services. And then you want to make the user aware of the limitations of their choice.

If your application requires location services to have any value, you need to let them know. But let them know in a subtle way. You don't want to do this in the form of a prompt. You just want to do this as part of your UI. Let them know in a meaningful and non-obtrusive way.

Region monitoring also gives you background updates automatically, even if your application is not currently running. Typically, for background updates with location services, you need to add the location string to the UI background mode's key in the info.p list. If you're only using region monitoring, though, this is not required.

Your application, as I said, will be launched into the background if an event comes in. So, when your application is woken up, Application Did Finish Launching with Options will be called, and you'll be handed a Launch Options Location Key that tells you that your application has been woken up by a location event. However, don't use this to solely check whether you need to set up a location manager or not.

You should always have a location manager set up if you're using any location-aware services. A situation that you could find yourself in is where a region event has come in and the user has just launched the application. If that happens, the Location Key may not come in with Application Did Finish Launching with Options. And in that case, you want to make sure that your location manager still gets set up so that you can receive events.

Let's see how this works. What happens here is that you have the system layer and location services. Now when a region is triggered, location services says, "I have a region event." Then, if your application is no longer running, it'll wake up the application in the background. Now this is when you need to set up your location manager.

If your application wasn't running, this may have been due to memory pressure on the OS and your application was jettisoned, or maybe the user restarted their device and hasn't run your application since. So now that you have your Location Manager set up, then Location Services can hand over the region event to the Location Manager, and the Location Manager can fire a delegate callback with the region that triggered the event.

If you don't have the Location Manager set up, what happens is that the region event starts with Location Services, moves to your application, but then the manager isn't there to respond, and so the region event just goes away. And it seems as if your application is no longer getting region events.

Now something that I've had many people ask about is what the battery consumption is like using region monitoring. Well, I'm happy to tell you that battery consumption for region monitoring is minimal. This is because we use all location data coming into the device to determine if a region has been entered or exited. Even if another application is using Core Location, any location data will also be used to figure out if a region event for your application has occurred.

You want to create a great user experience using region monitoring. Some ways to increase this user experience is by monitoring regions that are appropriate. Now, maybe I own a coffee shop, and when the user launches my app, I want to register some regions to let users know when they're near one of my shops.

The problem is, I don't want to register all 1,000 locations because that's not meaningful to the user. What you want to do is maybe grab their current location and then decide which regions would be most appropriate to monitor, or even let the user decide which locations they care about. You want to ensure that you're not inundating the user with prompts for things that they don't care about.

Now, remember that your application has a limit to how many regions it can set up at one time. This means that you may want to see which regions you're currently monitoring from time to time. You can do this using the monitored regions property of the location manager. This gives you an NS set of CL region objects that you can iterate through and check their identifiers. Additionally, if you find a region that you don't need to monitor anymore, you can then call stop monitoring for region on the location manager and pass in the CL region you want removed.

This will free up another spot for another region and ensure that you're not inundating the region. Now, when monitoring large regions, the first thing you want to do is check what the maximum region monitoring distance is. This will ensure that you can still monitor the large region that you want to. If your region radius is larger than this maximum distance, then the registration will fail.

So as you've seen, region monitoring is very easy to set up. You saw that it takes very little to get up and going. It also makes for very personal experiences because these are locations that the user is used to moving between within their daily life. Finally, you want to respect user choices when it comes to authorization. You don't want to hound the user to make certain choices, and you don't want to make your application non-responsive if they decide not to allow location services. You want to do the best thing that you can for your user.

Next, let's talk about geocoding. We've introduced a lot of new features for geocoding under iOS 5. Now, most people don't think about locations in the form of coordinates. They don't say, "Oh, I know where that coordinate is. It's two blocks to the left and north just a bit." But an address is more meaningful, and a lot more people understand what an address is.

But if you've never been to Cupertino, California, maybe you don't know what this address represents. So how can you make this even more meaningful to a user? Well, maybe just by telling them that it's a point of interest. This helps them get their bearings and understand what this location means.

So why would you geocode? Well, you want to describe a location in a meaningful way to the user. You want to provide them more meaningful information about a location other than just a set of coordinates or an address. You also want to make sure that you deliver information in a way that they can understand. And this usually means in the language of which they speak. You want to make sure that this information is localized to match their device's locale. This is how they consume information on their device.

So what's new in iOS 5? We have reverse geocoding. And we've had reverse geocoding before, for those of you who have used it, but we've done a whole lot of changes to it, and we've actually moved it out of the MapKit framework and moved it into the Core Location framework. Then, we've introduced forward geocoding. So now you can do reverse and forward geocoding. Then, we've made the results match your device's locale. Whatever locale your device is set to is how the information from a geocode will return. This does a lot of work for you.

Now for those of you who haven't used geocoding before, a reverse geocode is where you transform a coordinate into an address. Conversely, a forward geocode turns an address into a coordinate, a latitude and longitude value that you can use to plot on a map or use to display data to the user.

We do this using the new CL Geocoder class in iOS 5. The new CL Geocoder does both forward and reverse geocoding. And this is a fully asynchronous API. If you need to do more than one request, then just create additional CL Geocoders. Finally, this is a network-based service, so it does require a network connection.

Now, some great enhancements that we've done to geocoding is that a map is no longer necessary. You can display this data however you want. This also means that it deprecates MK Reverse Geocoder. But for those of you who have been using it with MK placemarks, those now inherit from the new CL placemark so that you can still plot these results on a map with ease.

The other new class we have is CL Placemark. This is how your geocoding request results will be returned. A CL Placemark contains location information, region information, address dictionaries of the location, and descriptive properties. Now these descriptive properties are really great. They're properties such as inland water, so if you're on a lake, it can give you the name of a lake.

If you're on an ocean, it'll give you the name of the ocean. And of course, you still need to have a network connection, so keep that in mind. And then you can also get this areas of interest property. Like at the beginning, you saw that I turned one infinite loop into Apple Inc. This is the kind of information that you can get out of your geocoding results.

Now you can see here I've done a reverse geocode on one infinite loop. And you can see that we get a lot of information like the sub-Thoroughfare, which is the building number, the thoroughfare, which is the street, and more additional information such as postal code, country, and that areas of interest property.

So how do you actually use CL Geocoder? Well, first you create a CL Geocoder object, and then you call one of the reverse or forward geocoding methods. These methods include a completion handler that you define so that you can execute some code once the geocoding request has returned.

The completion handler is in the form of a block. And this handler will return an array of sealed placemarks on success, and these are sorted by confidence. Based on the information that our geocoder receives, we may have found several locations that we think will work. So they will be sorted by how confident we are that the result is what you wanted. Now, if no result could be found, we're going to return nil. Additionally, if an error occurred, an NSError will be returned on failure.

So, why might a geocode fail? Well, if you have a way for the user to cancel the request, maybe they've done just that. You can use the cancelGeocode method and cancel a current request. Additionally, there could be no results for the geocode. Geocoding also requires a network connection, as I mentioned earlier. So, if there's a network error, you may not get a result.

In some situations, depending on cell towers and things like that, we may be able to give you the country in a reverse geocode. However, it's not a guarantee and don't bank on it. To do a reverse geocode, the first thing you need to do is create a sealed geocoder object.

This will do the geocoding for you. Then you need to create a location to reverse geocode. You can see here that I've created a location using a latitude and longitude value. Then you call reverseGeocodeLocation, passing in the location that you just created, and completion handler, which is the block that will execute when the geocoding request comes back. You can see here that I'm just grabbing the first object from the array. But you would want to check the whole array to make sure that you're using the best value possible. You would also want to check for the error in case the request failed.

You can also use the Address Dictionary capabilities for geocoding. You can create your geocoder object, and then you can create an address dictionary using the Address Book framework's keys and values. Then, you call Geocode Address Dictionary Completion Handler. This makes it really easy to use the Address Book with geocoding.

Now, to do forward geocoding, you still create a CL Geocoder object, but next, you create a string for the address. Now, if this is user input, you might want to sanitize the data to make sure that you're not attempting to geocode a phone number. From there, you just call geocodeAddressString completionHandler, again, grabbing the result from the placemarks array that get returned.

Finally, to narrow down a set of possible results, you can create a geocoder object and call GeocodeAddressStringInRegionCompletionH andler. This allows you to define a region that the result should be within. That way, if you're searching for a town, there may be a town with the same name in a nearby state. This region will narrow the results that come back.

Next, let's talk about some best practices when using the sealed geocoder. First, I told you that the completion handler is asynchronous. So, which thread is this run on when a request comes back? It's the main thread. So, make sure that you account for this in your application. Additionally, you only want to send one request per user action. It's not a good idea to: kick off the request and kick off a bunch of different requests at one time. Next, you want to reuse results when at all possible.

You can also use significant location changes so that as the user moves, then you decide you need to do a sealed geocode instead of doing constant geocoding as the user moves around. Finally, don't geocode in the background. Since the completion handler runs on the main thread, this is definitely not a good idea.

Now, you want to make sure that the user can read the results in their own language. What may look like a word in one language could differ by a lot in another language. And with geocoding, we have built-in support for over 30 languages, meaning that whichever locale the user's device is set to, we're going to try our best to make sure that the data coming back is in a language that they understand.

We also have added global coverage for geocoding. We currently support over 47 different regions and territories worldwide. You can also look for a tech note on Apple's Developer Center for an updated list. Now with geocoding results, we will try to match the user's locale from locality up. Here, you can see a reverse geocode that has been done in English. Notice how small the differences are when switching to Polish.

But if we switch to Russian, you can see that almost all of the information has changed. So we return locale matching results for locality values on up. With iOS 5, geocoding is easier than ever. You can now do forward and reverse geocoding, and we give you additional information like the areas of interest property. We match results to the device's locale. There's a lot of parsing work going on, and you don't have to provide a service for it.

Finally, let's talk about testing. Testing is one of the most important and often overlooked aspects of development. When your application goes on sale, you start to receive feedback from users that have bought your application. And usually, this feedback is in the form of app store reviews. Well, the last thing you want is to start getting feedback that says, "The app hangs if I deny location services," or, "It says it works in Europe, but it really doesn't work in Europe." So, how can you take care of this before you start getting this type of feedback? Testing location awareness in the past has been a bit difficult.

You had to drive around with your computer and device, testing different areas, and you can't always get on a flight and test other countries. So we've made some great additions to Xcode and the iOS Simulator to make testing location apps easier for you. Let's start with Xcode. In Xcode, we've added location support in multiple areas, like schemes and the debugger. We also allow you to simulate various scenarios like specific locations, a list of major cities, and you can also use a GPX file to simulate routes.

So what does a scheme do? Well, like any good plan, Xcode 4's schemes have three phases. Each phase has its own kind of result. The build phase is where targets are built, the test phase is where testing targets are run, and then launch phase launches an executable. So here you can see if you go in to edit a scheme, you can go to the Options tab and allow location simulation.

From here, you can set the default location for testing with this scheme, you can choose a major city, or you can define a GPX file to use. Schemes are really easy to get to from the toolbar in Xcode. What you can do is you can create multiple scenarios and easily switch between them. So here I have Sydney, and if I click on that, you can see that I have these other options to quickly and easily get between.

Additionally, in the debugger, we've also added the ability to change the location on the fly as you test with a device. You can switch between major cities, turn simulation off, and also use GPX files. So, we've added a lot to Xcode. And next, let's look at the iOS Simulator. This has been a sore spot for some location testing in the past, but with the new SDK, we've added a lot for you.

The simulator is now a fully-fledged location simulator. You get location prompts, status bar icons, location services menus, and the authorization states to check. And you can also reset the location warnings just like on a device. This makes it really easy to test a specific scenario over and over again. Additionally, we've added background location services into the simulator. You can also do significant location changes, and most importantly, you can do region monitoring now.

A really great feature that we've added is the ability to set the location to be any latitude and longitude value you want. From the menu bar, you can do this easily. You can also test locations and routes with some predefined values that we've added, such as all of the Apple stores, a bike ride, a city run, or a freeway drive. In talking about the simulator though, keep in mind, the simulator is just that, a simulation. It's similar to a device, it does its best to imitate a device situation, but it should be used, in your case, for development purposes. This should not be your final testing scenario.

Now, earlier I mentioned that you can simulate routes with GPX files. But what is a GPX file? GPX stands for GPS Exchange Format. And this is an open standard and it's an XML-based file that represents a collection of locations known as waypoints. This collection of locations, or waypoints, can create a route that you can simulate in Xcode and the simulator. Let's look at an example.

You can see here that it is XML based, so if you've worked with XML data in the past, this will look very familiar. Then you set up a track or a route, and each location is a track point. These include latitude, longitude, and you can add however many you want for testing your route.

When we simulate these routes, we iterate over each point at about one per second, so you can see the change quickly and know that your application is responding appropriately. You'll also see that if you have waypoints that are farther than one kilometer apart, we will create points in between to create a realistic set of results and iterate over those waypoints at the rate of one per second.

Finally, one thing that you can do to best prepare yourself for any crashes that may occur within your app once it's on the App Store is to create an Xcode archive with your final build. This includes the binary and DSIM file that maps addresses to code within your binary.

By submitting to the App Store with the same binary that's in this archive, you can ensure that any and all crash logs you receive will be able to be symbolicated within the Xcode organizer. This is a very helpful tip to follow so that you can narrow down issues as soon as they happen.

As you've seen, by using region monitoring on iOS, you can create very personal experiences for your users. And with the Geocoder, you can make sure that the user gets the full benefit from any location information you have to share with them. You can also be sure that it's in a language they understand. You've also learned how to use the tools available to create a first launch experience for your users, that is a great one. I'm excited to see how you use this information to create fun and interesting location-aware applications.