CoreLocation functions using several different mechanisms for determining a user's location. This includes GPS, cell-tower triangulation, and (according to reports) Wi-Fi network location databases. In older hardware that does not support GPS, this mechanism is expectedly missing. Each of these mechanisms varies in their accuracy, with GPS generally being considered the most accurate. However, regardless of what your target hardware supports, you can generally get a good sense of a user's location using CoreLocation.
Before you can begin developing your application with CoreLocation, you need to add the CoreLocation framework to your XCode project. This framework is located at:
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator2.0.sdk/System/Lbrary/Frameworks
You may change iPhoneSimulator2.0.sdk to match your application's target platform. Once this framework is included, you can begin developing location-aware applications.
The CLLocation object represents the actual location information. This includes not only latitude/longitude, but also speed, course, and altitude information. The CLLocation object is generated and returned by the CLLocationManager object. The CLLocationManager is used to deliver location events to your application via the CLLocationManagerDelegate protocol.
The CLLocationManager class allows you to specify various parameters to be used when determining location information. The distanceFilter parameter specifies how much a device must move laterally before a location update event is triggered. For example, if you were writing an application that tracks how far you drive over a period of time, you may want to have a larger distance filter set than you would for an application that tracks how far you walk over a period of time. Of particular importance is the desiredAccuracy parameter. This parameter specifies how accurate the location returned should be. There are 5 supported values for this parameter: kCLLocationAccuracyBest, kCLLocationAccuracyNearestTenMeters, kCLLocationAccuracyHundredMeters, kCLLocationAccuracyKilometer, and kCLLocationAccuracyThreeKilometers. The desired accuracy is one of the things that must be taken under consideration when scoping the requirements of your application. If you are looking for course grained location information -- that is, what city a user is in as opposed to which street corner they are standing at -- then you may not need to incur the penalties that highly accurate location information comes with. Performance is of key importance when determining what accuracy to require. This includes processing performance, battery life performance, as well as the amount of time required to provide the location. When you initially request a location, the CLLocationManager provides the quickest -- and least accurate -- location available. It then works to further refine the location to ensure it is the most accurate. If getting a rough location quickly is more important to your application than pinpointing exactly where your user is, then you may want to use a less accurate measure than someone else developing a geocaching application.
Now that we've discussed some of the basics of CoreLocation, let's take a look at how to include it within your application. To start, whatever object will be making use of the location information must implement the CLLocationManagerDelegate protocol. This protocol contains 2 methods:
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
and
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
The didFailWithError method is called whenever location services are unable to determine a user's location. This includes situations where a user denies your application permission to determine the location. The didUpdateToLocation method is called whenever a successful location has been performed. The newLocation parameter provides the new coordinate information, while the oldLocation parameter has the previous location information. If this is the first time that didUpdateToLocation has been called, oldLocation will be nil.
To start using CoreLocation, you must instantiate a CLLocationManager object like so:
#import
...snip...
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
// Set the delegate
locationManager.delegate = self;
// Set your accuracy and filter parameters here
locationManager.distanceFilter = ...
locationManager.desiredAccuracy = ...
[locationManager startUpdatingLocation];
...snip...
The startUpdatingLocation method begins the process of determining the user's location based on the specified parameters. When a successful location is determined, it will call didUpdateToLocation on the specified delegate object. We can now write out our delegate methods:
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
// Disable future updates to save power.
[locationManager stopUpdatingLocation];
NSLog(@"oldLocation : %@", oldLocation);
NSLog(@"newLocation : %@", newLocation);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
[locationManager stopUpdatingLocation];
NSLog(@"ERROR : %@", error);
}
You notice here that we call stopUpdatingLocation as soon as a location is determined. This is to preserve battery life, as location services do draw quite a bit of power. If you have specified a high level of accuracy, you may not want to stop updating immediately, as it takes a while to get very accurate location results.
This was a quick introduction into how the CoreLocation classes work. With the 3.0 firmware including Google Maps support, you should be able to get map-based applications up and running with little effort. If you can't wait until then, take a look at Route-Me for an EXCELLENT mapping component for your iPhone or iPod Touch. I'm using it in one of my applications, and can't recommend it highly enough.