Friday, October 21, 2011

Location Services : Standard Location Provider I

This series discusses the iPhone Location Services.  In this post, we begin implementing a StandardLocationProvider class.

Algorithm
In Location Services : Getting Started, we built and configured a "LSDemo" target in Xcode so that we may prototype without interfering with "HelloWorld".  Now let's start writing some code.

We will be prototyping the standard and significant-change location services.  Let's start with the standard location service.  As described in the Location Awareness Programming Guide, applications desiring the standard location service should follow these steps:
Once the service is started, the delegate object will be notified asynchronously as location data becomes available.

Standard Location Provider
Our strategy will be to encapsulate the prototype logic for each service in its own class.    Conceptually, we intend on providing a location to HelloWorld at some point.  With this in mind, let's write a "LocationProvider" class for each type of service.

Let's start with the standard location service.  Open Xcode and select File > New > New File... (or simply press ⌘N). Then select "Objective-C class" and click "Next".  This class will provide a location using the standard location service, so let's name it "StandardLocationProvider":

Click "Next", and the subsequent dialog will ask for a destination file group and build target.  By default, "HelloWorld" will be indicated for both.  However, we shall be using this class for prototyping, so set the group and target to "LSDemo" instead:

Click "Create" to finish the process.  The new class files should appear in the Project Navigator.

Location Manager
First, it's clear that we will need an instance of CLLocationManager to manipulate.  Let's make it an instance variable of StandardLocationProvider.  Open the header file (StandardLocationProvider.h)and declare the locationManager field:
#import <CoreLocation/CoreLocation.h>


@implementation StandardLocationProvider
{
    @private
    CLLocationManager *locationManager;
}

@end
As the Objective-C Programming Language explains,  the @private modifier restricts the scope of locationManager so that only instances of StandardLocationProvider can see it.  This way we do not publicly expose the internals of our implementation.  

Now open the implementation file (StandardLocationProvider.m)and define a constructor for StandardLocationProvider which instantiates CLLocationManager for the member field:
/*
 * Constructor.
 */
- (id)init {
    if (self = [super init]) {
        locationManager = [[CLLocationManager alloc] init];
    }
    return self;
}
Build and run the sandbox target to confirm there are no errors.

Configuration
The second step to using the standard location service is configuring the desired accuracy and distance filter on the location manager.  The specific member properties of CLLocationManager are:
  • desiredAccuracy
    • Measured in meters (double).
    • Represents maximum allowed margin of error (+/-) for location measurements.
    • Default value is kCLLocationAccuracyBest.
  • distanceFilter
    • Measured in meters (double).
    • Represents minimum distance location must change to trigger another notification.
    • Default value is kCLDistanceFilterNone.
These settings are where one tunes the standard location service to tailor an application's specific needs.  Since we are still prototyping, our needs are not yet clear; let's use the defaults for now and return to this later.

Build and run the sandbox target to confirm there are no errors.  We shall continue implementing StandardLocationProvider in the next post.