Monday, October 24, 2011

Location Services : Standard Location Provider II

This series discusses the iPhone Location Services.  In this post, we complete the StandardLocationProvider implementation.

Algorithm Review
Recall from Standard Location Provider I that these were the steps to using the standard location service:
  • Create an instance of CLLocationManager.
    • Done
  • Configure desiredAccuracy and distanceFilter.
    • Using defaults
  • Assign a CLLocationManagerDelegate.
  • Start the service.
In the previous post we adressed the first two steps.  Now let's proceed to the last two.

Location Manager Delegate
The third step to using the standard location service is assigning a delegate object to the location manager instance.  Let's look closer at CLLocationManagerDelegate.  From the protocol's perspective, there are essentially three kinds of updates:
Notice that many kinds of location services call back through the same delegate protocol.  Since we are only prototyping the standard location service, we are only interested in location events, and so we only need to implement these callback methods:
Let's make it so StandardLocationProvider itself implements his protocol.

First, open the header file (StandardLocationProvider.h) and add the protocol to the class declaration:
@interface StandardLocationProvider : NSObject<CLLocationManagerDelegate>
Then, open the implementation  file (StandardLocationProvider.m) and add these stub methods:
/*
 * CLLocationManagerDelegate protocol.
 */
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{
    NSLog(@"newLocation=%@", newLocation);
    NSLog(@"oldLocation=%@", oldLocation);
}

/*
 * CLLocationManagerDelegate protocol.
 */
- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error
{
    NSLog(@"error=%@", error);
}
Now we have our CLLocationManagerDelegate object.  Let's assign it to the CLLocationManager instance.  Add this snippet to the StandardLocationProvider constructor:
[locationManager setDelegate:self];
We shall return to the constructor momentarily.  

Starting the Service
We could just start the location service right after assigning the delegate.  Indeed, since we're prototyping, one might wonder why not.  Let's give it a try and see what happens.  Add this snippet to the StandardLocationProvider constructor (following the delegate assignment):
[locationManager startUpdatingLocation];
At this point the constructor should look something like this:
/*
 * Constructor.
 */
- (id)init
{
    if (self = [super init]) {
        locationManager = [[CLLocationManager alloc] init];
        [locationManager setDelegate:self];
        [locationManager startUpdatingLocation];
    }
    return self;
}
Build and run the sandbox target to confirm there are no errors.

Yay!  We have completed our StandardLocationProvider implementation.  The only thing that remains now is to hook it back into the sandbox "LSDemo" app.