“You are Here!” – Part I

A two-part-guide on using CoreLocation and MapKit Frameworks in iOS 5

Introduction

Developing iOS apps that can take advantage of the built-in GPS unit is a great way to add a new dimension to the user experience. You can quickly make your apps location-aware with minimal effort. In this post, I have assumed that you have a fair knowledge of basics of iOS Development, so won’t be explaining each and every minute step.

Apple’s description:

The Core Location framework lets you determine the current location or heading associated with a device. The framework uses the available hardware to determine the user’s position and heading. You use the classes and protocols in this framework to configure and schedule the delivery of location and heading events. You can also use it to define geographic regions and monitor when the user crosses the boundaries of those regions.

The iPhone is able to employ a number of different techniques for obtaining information about the current geographical location of the device. These mechanisms include GPS, cell tower triangulation and (the least accurate) by using the IP address of available Wi-Fi connections. The mechanism that is used by iOS to detect location information is, however, largely transparent to the application developer and the system will automatically use the most accurate solution available at any given time. In fact, all that is needed to integrate location based information into an iOS 5 iPhone application is an understanding of how to use the Core Location Framework.

In iOS, you can find the current coordinates by making a request to the Core Location component to start looking up location information. This works via a series of delegate messages passed to our application when Core Location starts updating. By default, the location hardware in our device is usually turned off (or otherwise in an idle state) so as not to needlessly drain power. In a nutshell we need to:

Getting Started

First thing, we must create a new View-based Application project. This is expected from you, so I am not explaining it here. Now, since we’re going to be using Core Location with our app, we need to add the Core Location framework to our project’s link phase. In Xcode, click on the project’s name at the top of the project navigator view. In the Linked Frameworks and Libraries section, click the “+” icon to add a new framework. Find the CoreLocation.framework entry, and add it. When you next link your project, the framework will be automatically included.

Now we just need to #import the header file <CoreLocation/CoreLocation.h> in order to use it in our class.

Setting up the Delegate

To begin setting up our class as a delegate, we need to set our class as a CLLocationManagerDelegate. You can do this by adding CLLocationManagerDelegate to the @interface definition line.

Next, in the header and implementation file, we need to add two delegate methods:

-(void)locationManager: (CLLocationManager *)manager didUpdateToLocation: (CLLocation *)newLocation fromLocation: (CLLocation *)oldLocation

-(void)locationManager: (CLLocationManager *)manager didFailWithError: (NSError *)error

The first method will be called when Core Location has new location data for us to process. We receive these messages both when we have better accuracy for a current location, or the device has moved. These messages can also come in quickly one after the other, or as a trickle. All this depends on the developer, how he wants to handle it.

The second method is used, if Core Location needs to report a failure of some kind. We need to properly handle these. Note that this method is technically optional, but it’s best to get into the habit of handling these.

Of course, there are other delegate methods as well, but they more relevant to higher level iOS development. We will stick to the basics for now.

Now, we also need a way to store where we are currently located. Since there’s no guarantee of when we’ll be told of our location, we need to store this information for the times when we need to reference it. So we need to do it in the delegate method. We also need to keep track of our Core Location manager instance. So, be sure to add the following to your class, and synthesize the same in the implementation:

@property (nonatomic,retain) CLLocationManager *locationManager;

@property (nonatomic,retain) CLLocation *currentLocation;

Receiving Messages

Now that the setup is out of the way, it’s on to the fun stuff. First, let’s implement the didUpdateToLocation method.

-(void)locationManager: (CLLocationManager *)manager didUpdateToLocation: (CLLocation*)newLocation fromLocation: (CLLocation *)oldLocation {

   self.currentLocation = newLocation;

   if(newLocation.horizontalAccuracy <= 100.0f){

        [locationManager stopUpdatingLocation];

      }

    CLLocationDistance distance = [newLocation distanceFromLocation: oldLocation];

    NSLog(@”Distance moved = %f meters”,distance);

}

We are doing three things here is:-

a) Saving the currentLocation for future reference. This will be done whenever the delegate method is called.

b) Next, we check the included accuracy against a preset expectation. We don’t want to leave Core Location running for any longer than we absolutely need it to. It drains the battery life of the device when it has to communicate with GPS satellites or power up the radio for location triangulation, so we want to turn it back off again as soon as we have a good-enough position.

c) Calculating the distance moved by the device.

Lastly, we need to implement the didFailWithError method:

-(void)locationManager: (CLLocationManager *)manager didFailWithError: (NSError*)error {

     //Handle error according to the type of error or give an alert to user.

     NSLog(@”Error message – %@”,[error description]);

}

Requesting Updates

After the delegate has been implemented, it’s time to actually setup Core Location and request location updates. To setup Core Location, you’ll want to do the following (usually in viewDidLoad() method):

locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = 100.0f;
[locationManager startUpdatingLocation];

This sets up a new CLLocationManager instance. We next set our current class as delegate to receive CLLocationManagerDelegate messages. Finally, we tell CoreLocation to start figuring out our position.

The default configuration for the location manager is to report updates whenever any changes are detected in the location of the device. The distanceFilter property of the location manager allows applications to specify the amount of distance the device location must change before an update is triggered. If, for example, the distance filter is set to 100 meters the application will only receive a location update when the device travels 100 meters or more from the location of the last update.

Since I put this setup code in the viewDidLoad method, I also need to remember to tell Core Location to stop updating should my view get unloaded. Thus, I placed the following line in my viewDidUnload() method:

[locationManager stopUpdatingLocation];

It’s important to remember to tell Core Location to stop sending messages to the delegate before the delegate could be freed, which could cause CoreLocation to attempt to send messages to a released object (which would cause a crash).

We can also find out the current location coordinates. Longitude and latitude values are stored as type CLLocationDegrees and may be obtained from a CLLocation object as follows:

CLLocationDegrees currentLatitude = currentLocation.coordinate.latitude;
CLLocationDegrees currentLongitude = currentLocation.coordinates.longitude;

Voila!! Its Done!

The final step prior to testing the application is to make sure that any memory allocated during the application lifecycle is released. This can be achieved within the viewDidUnload method.

An important note: If location updates are required when the application is in the background state it is strongly recommended that the desired accuracy setting be reduced within the applicationDidEnterBackground method by making a call to the startMonitoringSignificantLocationChanges method of the location manager object. This will ensure that the application is only notified of significant changes to the location of the device thereby reducing the load on the battery.

And that’s all there is to it! Implementing Core Location is an easy thing to implement and can add an interesting new dimension to your iOS apps. In the second part, we’ll implement the MapKit framework, which is even more interesting.

Happy Coding!!

References

http://developer.apple.com/library/ios/#documentation/userexperience/conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html

http://www.iosdevnotes.com/2011/10/ios-corelocation-tutorial/

http://www.techotopia.com/index.php/Getting_iPhone_Location_Information_using_the_iOS_5_Core_Location_Framework

4 thoughts on ““You are Here!” – Part I

  1. When i was working with the framework, i referred to all these links, but couldn’t find a comprehensive answer so here in my blog, I tried to sum up the posts from hither and thither. Changing the example code would not have helped as much as the compilation of a compendium of all the posts. So, you are right in a way that it is a summary but certainly will prove to be very useful to a noob.

Leave a Reply

Your email address will not be published. Required fields are marked *


9 + nine =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>